【问题标题】:Why isn't this template reactive?为什么这个模板不是反应式的?
【发布时间】:2015-10-09 02:19:04
【问题描述】:

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

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

Suspects.findOne('bruce') 不是已经返回了响应式对象吗?我尝试将human 答案直接放在布鲁斯身上,但它没有触发更新。

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

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

添加了 iron:router 的 Meteor 1.2:

<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');
  }
});

谢谢:-)

【问题讨论】:

    标签: meteor meteor-blaze meteor-helper


    【解决方案1】:

    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

    【讨论】:

    【解决方案2】:

    非常接近您只需要使用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'}});
        }
      });
    }
    

    【讨论】:

    • 嗯...我希望将数据留在 Bruce 上并保存到 Mongo。我需要将答案复印两份吗?另外,谢谢:-)
    • 另外,Suspects.findOne('bruce') 不是已经返回了响应式对象吗?
    • @MichaelCole 哦,是的,我没看到它错过了对不起。
    猜你喜欢
    • 1970-01-01
    • 2021-02-27
    • 1970-01-01
    • 1970-01-01
    • 2013-04-06
    • 1970-01-01
    • 2015-03-11
    • 2011-04-11
    • 1970-01-01
    相关资源
    最近更新 更多