Подтвердить что ты не робот

На простом английском языке, что делает Tracker.autorun?

Методы 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? Курсоры уже являются реакционным источником, и для того, чтобы сделать вещи более запутанными , следующий пример касается другого реакционного источника: Сеансы.

Работает ли Tracker.autorun только с реакционными источниками, и если да, то в чем преимущество использования их внутри Tracker? Сделать их вдвойне реакционными?

4b9b3361

Ответ 1

Чтобы реализовать реактивное программирование (вариант программирования, управляемого событиями), Meteor использует две различные концепции:

  • реактивные вычисления: фрагменты кода, которые будут повторно перезапускаться каждый раз при изменении их зависимостей.
  • источники реактивных данных: объекты, способные регистрировать зависимости, когда они используются внутри реактивного вычисления, чтобы сделать его недействительным и заставить его снова запустить с новым значением данных.

Эти два понятия реализуются двумя редко используемыми базовыми объектами Tracker, а именно Tracker.Comput и вспомогательным объектом Tracker.Dependency, который является контейнером для хранения набора вычислений.

A Tracker.Computation - объект с двумя важными методами:

  • invalidate(), что вызывает повторное вычисление.
  • onInvalidate(callback) для фактического запуска произвольного кода вычисления.

Когда вы вызываете Tracker.autorun, вы в основном создаете новое вычисление и регистрируете обратный вызов onInvalidate с передачей функции в качестве аргумента.

A Tracker.Dependency представляет собой набор вычислений с двумя методами.

  • depend(): добавляет текущее вычисление к набору.
  • changed(): при вызове аннулирует все зарегистрированные вычисления.

Когда реактивный источник данных регистрирует зависимость внутри вычисления, он вызывает Dependency.depend(), который просто добавляет текущее вычисление (если оно есть) к набору отслеживаемых вычислений.

Когда изменяется источник реактивной информации, он вызывает Dependency.changed(), который будет лишать законных результатов всех зарегистрированных вычислений в наборе.

Источник: Руководство по отслеживанию Meteor Tracker.

В структуре Meteor вы обычно имеете дело только с несколькими объектами более высокого уровня, реализующими концепции реактивного программирования.

  • реактивные вычисления порождаются с помощью Tracker.autorun, по умолчанию шаблонные помощники всегда запускаются внутри реактивного вычисления.
  • источники реактивных данных используют Tracker.Dependency для недействительности вычислений, к ним относятся курсоры MiniMongo, переменные Session, Meteor.user() и т.д.

Используйте Tracker.autorun, когда вам необходимо повторно перезапустить произвольный код вне помощников шаблонов, например внутри события шаблона onRendered lifecycle, используйте ярлык this.autorun (создайте реактивное вычисление, которое автоматически остановится, когда шаблон уничтожены), чтобы реагировать на любые изменения реактивных источников данных.

Вот небольшой пример шаблона, который подсчитывает, сколько раз вы нажимали кнопку и reset счетчик на 0 при нажатии 10 раз.

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