尽管可观察到的变化,但计算的可观察到的不会触发

Posted

技术标签:

【中文标题】尽管可观察到的变化,但计算的可观察到的不会触发【英文标题】:Computed observable not firing despite observable changing 【发布时间】:2019-09-29 21:41:03 【问题描述】:

我有以下几点:

sidebarCardVm.showCreateButton = ko.computed(function () 
    return
        (sidebarItemType == "Test") ||
        (sidebarItemType == "Test2" && self.selectedItem() != null); // when selectedItem() changes, I expect this to fire.  It does not.
);

我预计 selectedItem 的更改会触发此操作:

self.selectedItem = ko.computed(function () 
    var matchingCard = getSelectedCard("Item")
    if (matchingCard != null && matchingCard.selectedItem() != null)
        return matchingCard.selectedItem();
    return null;
);

但事实并非如此。我看到self.selectedItem 更新了,但showCreateButton 没有效仿。这是为什么呢?

【问题讨论】:

【参考方案1】:

计算对象在确定它们的依赖关系方面非常聪明。例如:

const myObs = ko.observable("Hello world");
const returnEarly = ko.observable(true);

const myComp = ko.computed(
  () => returnEarly() || myObs()
);

console.log(myComp()); // true
console.log(myObs.getSubscriptionsCount()); // 0

returnEarly(false);
console.log(myComp()); // "Hello world"
console.log(myObs.getSubscriptionsCount()); // 1
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.4.2/knockout-min.js"></script>

因为当exitEarly 仍然是true 时,代码永远不会到达调用myObs 的位置,因此不会创建订阅。只有当它到达|| 的第二部分时,我们才会开始为myObs 的新值触发更新。

因此,这段代码:

(sidebarItemType == "Test") ||
(sidebarItemType == "Test" && self.selectedItem() != null);

根据定义,可以创建selectedItem 的订阅。

每当sideBarItemType === "Test"时,它都会提前返回,不会调用selectedItem

【讨论】:

那么我是否只是将我的条件分解成一堆if 语句,首先出现可观察的条件?如果它训练人类期待某种行为,然后在极端情况下欺骗他们,这似乎并不聪明。 阅读我再次突出显示的代码中的语句。如果sidebarItemType 等于"Test",则&& 之后的部分将不需要得到false 的结果:这就是AND 运算符的定义。只有当a && b 中的a 部分为真时,才会评估b。现在,由于您包含了一个检查a||,所以事情会中断:a || (a && b) 将在a 为真时返回a,或者返回@ 987654345@。它永远不会返回b 我原来的帖子中有一个非常重要的遗漏。我正在针对a || (b & c) 进行测试 - 对造成的混乱表示歉意。无论哪种方式,我都将我的计算分解为 if/else 语句,以强制评估条件作为一种解决方法。

以上是关于尽管可观察到的变化,但计算的可观察到的不会触发的主要内容,如果未能解决你的问题,请参考以下文章

可观察到的数组更改不会反映在第一次点击 - KnockoutJS

可观察到的 forkJoin 没有触发

Knockout.js:当可观察数组中的值发生变化时触发计算的最佳方法是啥

在可观察到的变化上刷新 ViewModel

Angular2 beta.12 和 RxJs 5 beta.3 的可观察到的错误

角度形式控制最后可观察到的变化