我对 ko.computed 变量上定义的延迟计算的行为解释感到有些困惑。
这样的计算变量可以用属性 deferEvaluation:true 来定义,它应该将评估推迟到任何其他属性要求变量值的时刻(参见http://knockoutjs.com/documentation/computed-reference.html),
当常规ko.computed变量由 extend({deferred:true})扩展时,它会异步调用计算并推迟计算,直到所有当前正在运行的"线程"完成(见http://knockoutjs.com/documentation/deferred-updates.html)。
这两个设置听起来非常相似,但每个设置完全不同。
如果我弄错了,有人可以向我确认我是对的还是解释差异?
答案 0 :(得分:5)
deferEvaluation
仅限于推迟初始评估。通常,当您创建计算机时,其评估程序将同步调用然后,这意味着(除其他外)必须已初始化它所依赖的所有可观察对象。使用deferEvaluation
可以防止这种情况,并且第一次调用计算机的evalutor函数时会在第一次订阅计算机时发生(或者永远不会,如果没有的话)。在那之后,它没有进一步的效果;每当有任何依赖于变化的东西时,计算机仍然会立即重新评估。
.extend({deferred: true})
是关于始终推迟执行评估程序,直到创建或更改它的任务完成(然后通常在下一次UI更新之前)。它不仅仅是关于初始评估,它意味着每次计算的可观察量取决于变化时,允许通过使计算的评估异步(在当前任务之后)并等待它们稳定来解决这些变化。
以下是使用deferEvaluation
并使用.extend({deferred: true})
同时使用它们的代码段。请注意调用赋值程序时的差异。
setTimeout(function() {
console.log("---- Using neither:");
var ob1 = ko.observable(10);
console.log("creating c1");
var c1 = ko.computed(function() {
console.log("c1 evaluated");
return ob1() * 2;
});
console.log("Setting ob1 to 20");
ob1(20);
console.log("subscribing to c1");
c1.subscribe(function(newValue) {
console.log("c1's new value is " + newValue);
});
console.log("Setting ob1 to 30");
ob1(30);
console.log("Setting ob1 to 40");
ob1(40);
}, 50);
setTimeout(function() {
console.log("---- Using .extend({deferEvaluation: true}):");
var ob2 = ko.observable(10);
console.log("creating c2");
var c2 = ko.computed(function() {
console.log("c2 evaluated");
return ob2() * 2;
}, null, { deferEvaluation: true });
console.log("Setting ob2 to 20");
ob2(20);
console.log("subscribing to c2");
c2.subscribe(function(newValue) {
console.log("c2's new value is " + newValue);
});
console.log("Setting ob2 to 30");
ob2(30);
console.log("Setting ob2 to 40");
ob2(40);
}, 200);
setTimeout(function() {
console.log("---- Using .extend({deferred: true}):");
var ob3 = ko.observable(10);
console.log("creating c3");
var c3 = ko.computed(function() {
console.log("c3 evaluated");
return ob3() * 2;
}).extend({ deferred: true });
console.log("Setting ob3 to 20");
ob3(20);
console.log("subscribing to c3");
c3.subscribe(function(newValue) {
console.log("c3's new value is " + newValue);
});
console.log("Setting ob3 to 30");
ob3(30);
console.log("Setting ob3 to 40");
ob3(40);
}, 400);
.as-console-wrapper {
max-height: 100% !important;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.4.0/knockout-min.js"></script>
答案 1 :(得分:2)
deferEvaluation
将阻止计算机确定其初始值(和依赖关系),直到实际访问它为止。这可能是程序化的(访问代码中的计算机)或通过绑定。它可以用于鸡肉和鸡蛋&#34;计算机代码需要在运行之前等待其他事情设置的场景,或者如果在需要/读取其值之前初始化多次触发计算机的效率。 pureComputed
功能可以在计算(http://knockoutjs.com/documentation/computed-pure.html)的整个生命周期内完成同样的事情,并获得额外的好处。
extend({deferred: true})
会将observable / observableArray / computed选择为延迟更新功能。延迟更新意味着您可以同步对observable / observableArray或计算机的依赖项进行多次更新,它只会触发一次更改(异步发生)。这对于复杂的UI非常有用,因为您将避免多次重新渲染以进行中间更改。
如果我正在启动新应用程序,我会尽可能启用延迟更新(ko.options.deferUpdates = true
)并使用ko.pureComputed
以获得最佳性能和内存使用情况。