#javascript #meteor
#javascript #meteor
Вопрос:
Я просто пробую 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?
Ответ №1:
Это связано с тем, как работает Meteor.
Когда клиент запускается, у него еще нет никаких данных. Затем клиент открывает подписки на сервере (при условии, что у вас все еще установлен пакет автоматической публикации по умолчанию, это делается для вас), которые вскоре после этого отправляются через данные.
Именно эта часть «вскоре после» является проблемой здесь.
В вашем случае это означает, что при 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
функцию!