Meteor: "TypeError: undefined is not an object" when using collection
Meteor: "TypeError: undefined is not an object" when using collection
我只是在尝试 Meteor,我在 Javascript 方面也不是很先进。我正在尝试使用模板在客户端显示来自 collection 的 object 的文本 属性,但出现标题中提到的错误。我只是稍微修改了默认的 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 的工作原理有某种关系?
这与 Meteor 的工作原理有关。
客户端启动时,还没有任何数据。客户端然后打开与服务器的订阅(假设您仍然安装了默认的自动发布包,这是为您完成的),它会在不久之后发送数据。
这 "shortly afterwards" 部分就是这里的问题。
在您的情况下,这意味着当 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);
}
});
});
我还将反应性变量的创建从 auto运行 中移出,因为我们只想创建它一次,然后设置或获取它的值。
或者,我之前提到过助手会自动自动 运行。这意味着您可以在助手中找到推文来稍微简化您的模板:
Template.tweet.helpers({
text() {
var doc = Tweets.findOne();
if (doc) return doc.text;
},
});
更好的是,我们不再需要 ReactiveVar
并且可以删除整个 onCreated
函数!
我只是在尝试 Meteor,我在 Javascript 方面也不是很先进。我正在尝试使用模板在客户端显示来自 collection 的 object 的文本 属性,但出现标题中提到的错误。我只是稍微修改了默认的 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 的工作原理有某种关系?
这与 Meteor 的工作原理有关。
客户端启动时,还没有任何数据。客户端然后打开与服务器的订阅(假设您仍然安装了默认的自动发布包,这是为您完成的),它会在不久之后发送数据。
这 "shortly afterwards" 部分就是这里的问题。
在您的情况下,这意味着当 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);
}
});
});
我还将反应性变量的创建从 auto运行 中移出,因为我们只想创建它一次,然后设置或获取它的值。
或者,我之前提到过助手会自动自动 运行。这意味着您可以在助手中找到推文来稍微简化您的模板:
Template.tweet.helpers({
text() {
var doc = Tweets.findOne();
if (doc) return doc.text;
},
});
更好的是,我们不再需要 ReactiveVar
并且可以删除整个 onCreated
函数!