我只是在尝试Meteor,而且我对Javascript的总体了解也不高。我正在尝试使用模板在客户端的集合中显示对象的文本属性,但是出现标题中提到的错误。我刚刚修改了默认的Meteor基础项目。
main.html:
<head>
<title>Test</title>
</head>
<body>
<section>
{{> tweet}}
</section>
</body>
<template name="tweet">
<h1 class="mt-5">{{text}}</h1>
</template>
main.js
import { Template } from 'meteor/templating';
import { ReactiveVar } from 'meteor/reactive-var';
import './main.html';
import 'bootstrap/dist/js/bootstrap.bundle';
Tweets = new Mongo.Collection('tweets');
Template.tweet.onCreated(function tweetOnCreated() {
var txt = Tweets.findOne().text;
this.text = new ReactiveVar(txt);
});
Template.tweet.helpers({
text() {
return Template.instance().text.get();
},
});
var txt = Tweets.findOne().text;
有什么问题?我在这里对Javascript有一个普遍的误解吗?还是这个错误与Meteor的工作方式有关?
答案 0 :(得分:2)
这与流星的工作方式有关。
客户端启动时,尚无任何数据。然后,客户端通过服务器打开订阅(假设您仍然安装了默认的自动发布程序包,此操作已为您完成),此后不久将通过数据发送。
这是“此后不久”的部分。
对于您而言,这意味着Tweets.findOne()
运行时还没有数据,因此没有文档可以读取text
。因此错误。通过检查是否返回文档来防止错误:
Template.tweet.onCreated(function () {
var doc = Tweets.findOne();
if (doc) {
this.text = new ReactiveVar(doc.text);
}
});
如果您尝试这样做,该错误将消失,但仍不会显示任何文本。
因此,现在我们希望当数据可用时,该部分代码再次运行。 Blaze会自动在助手中执行此操作,但是您需要将其包装在autorun
中的其他地方:
Template.tweet.onCreated(function () {
this.text = new ReactiveVar();
this.autorun(() => {
var doc = Tweets.findOne();
if (doc) {
this.text.set(doc.text);
}
});
});
我也将反应式var的创建移出了自动运行,因为我们只想创建一次,然后设置或获取其值。
或者,我之前提到过,助手会自动运行。这意味着您可以在帮助器中找到该推文以简化您的模板:
Template.tweet.helpers({
text() {
var doc = Tweets.findOne();
if (doc) return doc.text;
},
});
更好的是,我们不再需要ReactiveVar
,可以删除整个onCreated
函数!