Knockout - ko.computed和ko.observable.subscribe之间的区别

时间:2016-08-24 07:25:19

标签: knockout.js

我的viewmodel中有一个函数循环遍历数组并查看 对于具有相似ID的项目(我知道它是错误的,因为ids是唯一的,当我解决此问题时会将其更改为某些自定义数据属性)并检查它们是否找到。这是功能:

/*
  Search for similar terms in taxonomy,
  if found check/uncheck them
*/

self.srcSimilar = function(tid,val){
  _.filter(self.topics(), function(topic) {
    return _.any(topic.children, function(member) {
      tid === member.tid ? member.isSelected(val) : '';
      return _.any(member.children, function(child) {
        tid === child.tid ? child.isSelected(val) : '';     
      });
    });
  }); 
}

从现在开始,该函数已在child.is的.subscribe方法中被调用。选择了observable,如下所示:

child.isSelected.subscribe(function(val){
    self.srcSimilar(child.tid,val);
});

现在我需要在计算的observable中转换child.isSelected observable,因为checked / unchecked状态取决于插入selectedItems可观察数组中的子节点。所以我将child.isSelected observable改为:

child.isSelected = ko.computed({
  read: function(){
  },
  write: function(val){
    self.srcSimilar(child.tid,val);
  }
});

...但这最终导致控制台中出现“过多的递归”错误。 我在这里遗漏了一些东西,不明白为什么.subscribe有效,而ko.computed写入方法在一个递归中被卡住了。 谢谢你的帮助。

1 个答案:

答案 0 :(得分:2)

传递给subscribe的函数仅在child.isSelected CHANGES时调用。这意味着如果self.srcSimilar在调用self.srcSimilar的同一个子节点上设置isSelected,则不会再次触发更改事件,因为该值已经设置且该方法不会递归。

然而,对于计算,只要设置了child.isSelected,就会调用为write定义的方法。

想象一个数据集,其中A类似于B.

使用Computed

  1. 使用isSelected(true)设置A,调用计算机的写入。
  2. 使用A.tid调用
  3. self.srcSimilar。
  4. self.srcSimilar由于A.tid === B.tid。
  5. 而找到B.
  6. B由self.srcSimilar设置为isSelected(true),调用计算的B写入。
  7. 使用B.tid调用self.srcSimilar。
  8. self.srcSimilar由于B.tid === A.tid
  9. 而找到A.
  10. 通过self.srcSimilar设置isSelected(true),调用计算的A write
  11. 转到步骤#2
  12. 订阅

    1. A由调用传递给subscribe的函数的东西设置。
    2. 使用A.tid 调用
    3. self.srcSimilar
    4. self.srcSimilar由于A.tid === B.tid。
    5. 而找到B.
    6. 由self.srcSimilar设置为isSelected(true),调用传递给subscribe的函数。
    7. 使用B.tid
    8. 调用self.srcSimilar
    9. self.srcSimilar由于A.tid === B.tid。
    10. 而找到B.
    11. 使用isSelected(true)设置A,但是因为isSelected已经为true,所以不会调用传递给subscribe的函数。