用简单的英语,Tracker.autorun做什么?

时间:2015-05-30 12:56:55

标签: javascript meteor

Tracker方法并不完全属于Meteor功能的核心,很少用于教程和初学者书籍(如果它们没有得到很好的解释),结果被认为更加“可怕” “比其他大部分框架都要好。

我是一个人,从来没有设法将Tracker.autorun与我的项目争论,因为它似乎永远不会对它有所期待。这就是文档所说的:

  

立即运行一个函数,并在以后重新运行它的依赖项   变化

对我而言,这听起来像是一种让非反动的资源反动的方式,但是接下来你会看到这样的例子,其中第一个看起来像这样:

Tracker.autorun(function () {
  var oldest = _.max(Monkeys.find().fetch(), function (monkey) {
    return monkey.age;
  });
  if (oldest)
    Session.set("oldest", oldest.name);
});

与不使用Tracker.autorun有何不同?游标已经是反动的来源,让事情变得更加混乱下一个例子涉及另一个反动源:Sessions。

Tracker.autorun仅适用于反动来源,如果是,那么在Tracker内使用它们有什么好处?让他们倍加反动?

1 个答案:

答案 0 :(得分:37)

为了实现反应式编程(事件驱动编程的一种变体),Meteor使用了两个不同的概念:

  • 反应计算:每次修改其基础依赖关系时将被反应重新运行的代码片段。
  • 反应数据源:在反应计算中使用时能够注册依赖关系的对象,使其无效并使其与新数据值一起运行。

这两个概念是由两个很少使用的底层Tracker对象实现的,即Tracker.Computation和帮助对象Tracker.Dependency,它是一个用于存储一组计算的容器。

Tracker.Computation是一个有两个重要方法的对象:

  • invalidate(),导致计算重新运行。
  • onInvalidate(callback)实际运行计算任意代码。

当您致电Tracker.autorun时,您基本上创建了一个新计算并使用您传递的函数注册onInvalidate回调。

Tracker.Dependency是包含两种方法的计算集合。

  • depend():将当前计算添加到集合中。
  • changed():调用时,会使每个已注册的计算无效。

当一个被动数据源在计算中注册一个依赖项时,它正在调用Dependency.depend(),它只是将当前计算(如果有的话)添加到一组被跟踪的计算中。

当修改了被动数据源时,它正在调用Dependency.changed(),它将使集合中的每个已注册计算无效。

来源:The Meteor Tracker manual

在Meteor框架中,您通常只处理实现反应式编程概念的几个更高级别的对象。

  • 使用Tracker.autorun生成反应计算,默认模板帮助程序始终在反应计算中运行。
  • 被动数据源正在使用Tracker.Dependency使计算无效,它们包括MiniMongo游标,Session变量,Meteor.user()等......

当您需要在模板帮助程序之外反应性地重新运行任意代码时使用Tracker.autorun,例如在模板onRendered生命周期事件中,使用快捷方式this.autorun(产生一个反应计算,即在模板被销毁时自动停止)以对任何被动数据源修改作出反应。

以下是模板的一个小示例,它计算单击按钮的次数,并在单击10次时将计数器重置为0.

HTML

<template name="counter">
  <div class="counter>
    <button type="button">Click me !</button>
    <p>You clicked the button {{count}} times.</p>
  </div>
</template>

JS

Template.counter.onCreated(function(){
  this.count = new ReactiveVar(0);
});

Template.counter.onRendered(function(){
  this.autorun(function(){
    var count = this.count.get();
    if(count == 10){
      this.count.set(0);
    }
  }.bind(this));
});

Template.counter.helpers({
  count: function(){
    return Template.instance().count.get();
  }
});

Template.counter.events({
  "click button": function(event, template){
    var count = template.count.get();
    template.count.set(count + 1);
  }
});