如果两个依赖路径改变为可观察的,则Knockout在单个动作上计算多次触发

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了如果两个依赖路径改变为可观察的,则Knockout在单个动作上计算多次触发相关的知识,希望对你有一定的参考价值。

我有一个可观察的A绑定到UI元素。我还有一个取决于A的计算B。我有一个取决于A和B的计算С。我有一个订阅C

当UI元素中的值发生更改时,计算结果将被计算两次,订阅将被调用两次。

我认为原因是A有两个订阅:A:[B,C] Knockout通知B关于A的变化。 在评估B之后,它通知C关于B的变化 然后它回到开始并调用A的第二个订阅,即C. 这里我们有两个C调用。

有办法防止这种情况吗?

var viewModel = {
    firstName: ko.observable("Andrew"),
    lastName: ko.observable("King"),
};

viewModel.fullName = ko.computed(function() {
    return viewModel.firstName() + " " + viewModel.lastName();
});

viewModel.user = ko.computed(function() {
    return {
    fullName: viewModel.fullName(),
    lastName: viewModel.lastName()
  };
});

viewModel.user.subscribe(function() {
    // This is called once if I change first name
    // It is called twice if I change last name
});

http://jsfiddle.net/jngxwf5v/

答案

当其中一个依赖项发生更改时,observable会重新计算。由于您在每次运行时都在创建一个新对象,因此淘汰赛无法判断某些内容是否真的发生了变化。

使用延迟计算修复它

为了防止它在两个依赖项发生更改时多次运行,可以将其延迟:

var viewModel = {
    firstName: ko.observable("Andrew"),
    lastName: ko.observable("King"),
};

viewModel.fullName = ko.computed(function() {
    return viewModel.firstName() + " " + viewModel.lastName();
});

viewModel.user = ko.computed(function() {
    return {
    fullName: viewModel.fullName(),
    lastName: viewModel.lastName()
  };
}).extend({ deferred: true });

viewModel.user.subscribe(function(user) {
  console.log(user);
});

viewModel.firstName("John");
viewModel.lastName("Doe");
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.4.2/knockout-min.js"></script>

以上是关于如果两个依赖路径改变为可观察的,则Knockout在单个动作上计算多次触发的主要内容,如果未能解决你的问题,请参考以下文章

观察者模式

当使用knockout.js和Sammy.js时,如何设置内容来自模板的可观察路径

Knockout学习笔记--使用计算属性

如何在 Knockout 中创建计算的可观察数组

详解Java设计模式之观察者模式(Observer Pattern)

详解Java设计模式之观察者模式(Observer Pattern)