knockout.js - 什么时候计算项目重新计算依赖项?

时间:2012-12-07 16:49:25

标签: knockout.js computed-observable

假设您有以下js:

  var vm = {
    objects: ko.observable([]),
    objectCount: ko.computed(function(){
      return vm && vm.objects().length;
    }),

    add: function() {
      var current = vm.objects();
      current.push({});      
      console.log('current is', current);
      vm.objects(current);
      console.log("should recalculate here", vm.objectCount());
    }
  };

以下html:

  <ul data-bind="foreach: objects">
    <li>
      Object: <span data-bind="text: $index"></span>
    </li>
  </ul>
  <button data-bind="click: add">Add Object</button>
  <p>
    Total number of objects:
    <span data-bind="text: objectCount"></span>
  </p>

这是我的理解from reading the documentation,因为在我添加一个对象之后我调用了objectCount(),它应该重新计算它的依赖关系。相反,它似乎永远不会执行该功能,只运行一次!

JSBin demonstrating a simplified version of my issue.

3 个答案:

答案 0 :(得分:4)

在定义viewModel之后定义你的计算机 - http://jsbin.com/welcome/58760/ - 它的发生是因为计算的observable的工作方式(来自ko docs)。

  1. 每当你声明一个计算的observable时,KO立即调用 它的评估函数得到它的初始值。
  2. 当您的评估程序功能正在运行时,KO会保留任何日志 您的评估者读取的可观察量(或计算的可观察量) 的价值。
  3. 当您的评估者完成后,KO会为每个评估者设置订阅 你所触及的观察者(或计算出的观察者)。该
    订阅回调设置为使评估者再次运行,
    将整个过程循环回到步骤1(处理任何旧的 订阅不再适用)。
  4. KO通知任何订阅者您计算的新值 观察到。
  5. 在vm对象中实例化observable时,其他属性尚不存在。

答案 1 :(得分:2)

这只是一个范围问题。如果您将脚本代码重构为如下所示:

$(function(){
  var vm = function(){
    var self = this;

    self.objects = ko.observable([]);
    self.objectCount = ko.computed(function(){
      return self.objects().length;
    });

    self.add = function() {
      var current = self.objects();
      current.push({});      
      console.log('current is', current);
      self.objects(current);
      console.log("should recalculate here", self.objectCount());
    };
  };

  ko.applyBindings(new vm());
});

然后正确的变量是作用域的,Knockout正确地计算了依赖关系。正如guigouz所述,最初调用ko.computed时,vm未定义,因此无法设置任何更改处理程序。

这是the updated JSBin

答案 2 :(得分:2)

另一种方法是使用deferEvaluation的{​​{1}}选项。这将告诉Knockout在第一次使用之前等待评估计算的observable。到那时,ko.computed将被定义。

vm