deferEvaluation 和 extend({deferred: true}) 之间 ko.computed 有什么区别
What is difference on ko.computed between deferEvaluation and extend({deferred: true})
我对 ko.computed 变量上定义的延迟计算的行为解释有点困惑。
这样的计算变量可以用 属性 deferEvaluation: true 定义,它应该将评估推迟到任何其他 属性 要求变量值(见 http://knockoutjs.com/documentation/computed-reference.html),
当常规 ko.computed 变量被 extend({deferred: true}) 扩展时,它异步调用计算并将其推迟到所有当前 运行 "threads" 完成(参见 http://knockoutjs.com/documentation/deferred-updates.html)。
这两个设置听起来很相似,但它们的作用完全不同。
任何人都可以向我确认我是对的或者如果我弄错了可以解释一下区别吗?
deferEvaluation
只是关于推迟 初始 评估。通常,当您创建一个计算对象时,它的求值器会在 之后 同步调用,这意味着(除其他事项外)它所依赖的所有可观察对象都必须已经初始化。使用 deferEvaluation
可以防止这种情况发生,并使对计算函数的评估函数的第一次调用发生在第一次订阅计算函数时(或者永远不会,如果没有)。之后,它没有进一步的影响;计算仍然是 re-evaluated 每当它依赖于任何变化时,立即。
.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>
deferEvaluation
将阻止计算确定其初始值(和依赖项),直到某些东西实际访问它。这可以是编程的(访问代码中的计算)或通过绑定。它对于 "chicken and egg" 计算的代码需要在 运行 之前等待其他设置的场景或者如果计算将在其值 [=23 之前在初始化中被触发多次的情况下提高效率的情况很有用=]. pureComputed
功能可以完成同样的事情,并在计算 (http://knockoutjs.com/documentation/computed-pure.html) 的生命周期内带来额外的好处。
extend({deferred: true})
将选择 observable/observableArray/computed 加入延迟更新功能。延迟更新意味着您可以同步对 observable/observableArray 或计算的依赖项进行多次更新,并且只会触发一次更改(异步发生)。这对复杂的 UI 非常有益,因为您将避免多次 re-renders 进行中间更改。
如果我开始一个新的应用程序,我会打开延迟更新 (ko.options.deferUpdates = true
) 并尽可能使用 ko.pureComputed
以获得最佳性能和内存使用。
我对 ko.computed 变量上定义的延迟计算的行为解释有点困惑。
这样的计算变量可以用 属性 deferEvaluation: true 定义,它应该将评估推迟到任何其他 属性 要求变量值(见 http://knockoutjs.com/documentation/computed-reference.html),
当常规 ko.computed 变量被 extend({deferred: true}) 扩展时,它异步调用计算并将其推迟到所有当前 运行 "threads" 完成(参见 http://knockoutjs.com/documentation/deferred-updates.html)。
这两个设置听起来很相似,但它们的作用完全不同。
任何人都可以向我确认我是对的或者如果我弄错了可以解释一下区别吗?
deferEvaluation
只是关于推迟 初始 评估。通常,当您创建一个计算对象时,它的求值器会在 之后 同步调用,这意味着(除其他事项外)它所依赖的所有可观察对象都必须已经初始化。使用 deferEvaluation
可以防止这种情况发生,并使对计算函数的评估函数的第一次调用发生在第一次订阅计算函数时(或者永远不会,如果没有)。之后,它没有进一步的影响;计算仍然是 re-evaluated 每当它依赖于任何变化时,立即。
.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>
deferEvaluation
将阻止计算确定其初始值(和依赖项),直到某些东西实际访问它。这可以是编程的(访问代码中的计算)或通过绑定。它对于 "chicken and egg" 计算的代码需要在 运行 之前等待其他设置的场景或者如果计算将在其值 [=23 之前在初始化中被触发多次的情况下提高效率的情况很有用=]. pureComputed
功能可以完成同样的事情,并在计算 (http://knockoutjs.com/documentation/computed-pure.html) 的生命周期内带来额外的好处。
extend({deferred: true})
将选择 observable/observableArray/computed 加入延迟更新功能。延迟更新意味着您可以同步对 observable/observableArray 或计算的依赖项进行多次更新,并且只会触发一次更改(异步发生)。这对复杂的 UI 非常有益,因为您将避免多次 re-renders 进行中间更改。
如果我开始一个新的应用程序,我会打开延迟更新 (ko.options.deferUpdates = true
) 并尽可能使用 ko.pureComputed
以获得最佳性能和内存使用。