为什么这个模板不是反应式的?

Why isn't this template reactive?

为什么这不是反应式的?更重要的是,如何让它具有反应性?

我希望将数据保存在 Mongo 中并在模板中使用。我可以使用 ReactiveVar 或 ReactiveDict。我需要两份数据吗?

Suspects.findOne('bruce') return 不是反应对象吗?我尝试将 human 答案直接放在 Bruce 上,但没有触发更新。

事件触发,log(this) 显示布鲁斯的答案已更改,但模板没有重新呈现。这样做的好方法是什么?

http://meteorpad.com/pad/KoH5Qu7Fg3osMQ79e/Classification

它是 Meteor 1.2 添加了 iron:router:

<head>
  <title>test</title>
</head>

<template name="question">
  {{#unless isAnswered 'human'}}   <!--  :-<  I'm not reacting here -->
    <div>Sir, are you classified as human?</div>
    <button id="no">No, I am a meat popsicle</button>
    <button id="smokeYou">Smoke you</button>
  {{else}}
    <div> Classified as human?  <b>{{answers.human}}</b></div>
  {{/unless}}
</template>

和 JavaScript:

// Why isn't this reactive?
if (Meteor.isClient) {
  Template.question.helpers({
    isAnswered: function (question) {     // :-<  I'm not reactive
      var suspect = Template.instance().data;
      return (typeof suspect.answers[question] !== 'undefined');
    }
  });

  Template.question.events({
    'click #no': function () {
      this.answers.human = "No"; // :-<  I'm not reactive
      console.log(this);
    },
    'click #smokeYou': function() {
      this.answers.human = "Ouch";    // :-<  I'm not reactive
      console.log(this);
    }
  });
}

// Collection
Suspects = new Meteor.Collection('suspects');
if (Meteor.isServer) {
  Meteor.startup(function () {
    // code to run on server at startup
    Suspects.upsert('bruce', { quest: 'for some elements', answers: {}});
  });
  Meteor.publish('suspects', function() {
    return Suspects.find({});
  });
}

// Iron Router
Router.route('/', {
  template: 'question',
  waitOn: function() {
    return Meteor.subscribe('suspects');
  },
  data: function() {
    return Suspects.findOne('bruce');
  }
});

谢谢 :-)

非常接近,你只需要根据它的声音使用 ReactiveVar 它几乎可以解释它是什么:) http://docs.meteor.com/#/full/reactivevar

下面是使用方法

if (Meteor.isClient) {
  Template.question.onCreated(function () {
    this.human = new ReactiveVar();
  });

  Template.question.helpers({
    isAnswered: function (question) {
      return Template.instance().human.get();
    }
  });

  Template.question.events({
    'click #no': function (e, t) {
      t.human.set('No');
      console.log(t.human.get());
    },
    'click #smokeYou': function(e, t) {
      t.human.set('Ouch');
      console.log(t.human.get());
    }
  });
}

更新:如果您使用游标,我通常喜欢将其保留在模板级别而不是铁路由器上:

if (Meteor.isClient) {
  Template.question.helpers({
    isAnswered: function (question) {
      return Suspects.findOne('bruce');
    }
  });

  Template.question.events({
    'click #no': function (e, t) {
      Suspects.update({_id: ''}, {$set: {human: 'No'}});
    },
    'click #smokeYou': function(e, t) {
      Suspects.update({_id: ''}, {$set: {human: 'Ouch'}});
    }
  });
}

events 实际上并没有更新反应数据源(数据库记录)。而不是做:

Template.question.events({
  'click #no': function () {
    this.answers.human = "No";
  }
});

事件需要执行数据库操作,可以通过直接 update 或通过 Meteor.call()Meteor.method。例如:

'click #no': function(){
  Suspects.update('bruce', {'answers': {'human': 'no'}});
}

如果您使用此模式,您还需要设置正确的 allowdeny 规则以允许从客户端代码进行更新。 http://docs.meteor.com/#/full/allow。方法通常最终成为更大项目的更好模式。

此外,我不确定您的 helper 中的 Template.instance().data 是否会反应。我会使用 Template.currentData() 代替只是为了确定。 http://docs.meteor.com/#/full/template_currentdata