初学者无需了解这些 ,但是很多高级程序员想知道我们为什么可以保持跟踪这些依赖以及可以正确的更新到UI中。它其实很简单。跟踪算法是这样的:

  1. 无论何时你定义了一个computed observable,KO 立即执行它的执行函数来获取初始值。
  2. 当执行函数正在运行,KO会在执行函数中所有使用到的observables之间(包括其它的computed observable)建立订阅关系。这个订阅回调必定使执行函数再次运行,循环整个过程回到第一步(释放所有的订阅关系并且不再使用)。
  3. KO想所有订阅者通知你的computed observable的新值消息。

所以,KO并不只是在第一次运行执行函数的时候发现依赖关系-它会在每一次执行的时候都再发现测依赖关系。这意味着这些依赖可以动态变化:依赖A可以决定computed observable是否也依赖于B或C。然后它只会在A或者B或C变化时被重新执行一次。 你不需要声明依赖,它们在代码运行时确定。

另一个巧妙的技巧是声明式绑定作为computed observables来简单实现。这样,如果一个绑定读取一个observable的值,那个绑定就依赖于了这个observable,当它发生变化的时候就会重新激活这个绑定。(原文是The other neat trick is that declarative bindings are simply implemented as computed observables. So, if a binding reads the value of an observable, that binding becomes dependent on that observable, which causes that binding to be re-evaluated if the observable changes.这个地方我感觉翻译的有毛病。)

使用peek控制依赖

KO的自动依赖跟踪通常能准确的知道你想要什么。但是你有时可能需要控制哪些observable将要更新你的computed observable,尤其是如果这个computed observable执行一个很简短的行为例如发送一个ajax请求。. peek方法让你可以无需创建依赖就能访问一个observable或者computed observable。

在下面的例子中,computed observable使用ajax来重新为一个叫做currentPageData的observable加载数据,它向服务器传递的数据params中有两个observable属性,也就是说无论何时pageIndex属性发生了变化这个computed observable 都将会更新,也就是会运行json的请求, 但是它忽略了selectedItem的变化,因为它使用peek来进行访问. 在这种情况下,当一系列新的数据加载的时候,用户可能希望为了追踪的目的只使用selectedItem的当前值 。

ko.computed(function() {
var params = {
page: this.pageIndex(),
selected: this.selectedItem.peek()
};
$.getJSON('/Some/Json/Service', params, this.currentPageData);
}, this);

注意: 为什么循环依赖没有意义

Computed observables 应该是将一些observable输入映射为一个单独的observable输出。这样的话在你的依赖链中形成循环是毫无意义的。 循环可能并不像递归;他们将类似于有两个电子表格单元,计算彼此的功能. 这将导致一个无限的循环。

那么如果你在你的依赖中出现了循环依赖那么ko会怎么处理呢? 它通过下面的规则来避免无限的循环::如果computed正在被执行 Knockout 将不会重新激活(执行)它。 这不会影响你的代码。在两种情况下是相关的: 当两个compute observables相互依赖,或者当一个computed observable 向另外一个拥有依赖的observable写入数据的收 (直接写或者通过一个依赖链中). 如果您需要使用这些模式之一,并希望完全避免循环依赖,您可以使用上面所述的peek功能。

总结说明,这一节算是翻完了,但是很多知识点理解上还是有问题。这一节的重点就是那个peek,它的主要作用就是:如果computed observable中使用了其它的observable,那么当那些observable有更新的时候会让这个computed observable再执行一次,如果这里面有ajax操作或其它耗时操作没有必要,那么我们使用peek可以单向解除这个依赖,当那些observable更新时使得我们computed observable无需跟着更新。

04-16 14:21