我无法让afterRender触发一次。我看到afterRender被触发两次,因为我的模板绑定中有两个observable同时更新:
<div data-bind="template: { name: template.name(), data: template.data, if: template.data, afterRender: doSomeStuff }">
</div>
这是因为对name
的更新会触发对data
的更新,因为它是一个计算的observable,其值取决于名称:
this.data = ko.computed({
var viewName = this.name();
switch (viewName) {
case "a":
return this.modelA();
case "b":
return this.modelB();
case "c":
return this.modelC();
default:
return null;
}
});
我要做的是记录模板渲染的时间。我还担心渲染两次可能会对性能产生影响 - 模板中的那些DOM元素是每次name
更改一次创建的两次吗?
可能data
更改(例如,modelA,modelB或modelC对象更改)而name
没有更改,我希望data
更改为afterRender
触发afterRender,如果它自己更改。理想情况下,我可以将名称数据更新结合到触发deferEvaluation
一次,但我不确定这是否可行。
有没有一种优雅的方法来实现这一目标?
data
关于
template.name
计算的observable似乎不会导致模板
data
更改时绑定以获取新对象(不是
确定这是因为模板绑定实际上并非如此
在template.name
更改时重新评估with
,并且仍应触发模板绑定两次。我正在考虑完全摆脱数据对象,并在每个HTML模板中,将{{1}}绑定直接附加到modelA,modelB和modelC,但是如果是的话我不会得到那些afterRender更新数据变化。
编辑:我正在使用KO 2.2.1,并意识到模板名称不可观察(直到2.3.0),因此在template.name之后的括号。所以我最初假设这个afterRender发生两次因为名字是一个可观察的也必须是不正确的?
答案 0 :(得分:2)
使用计算的observable更新绑定,该observable跟踪对任何依赖项的更改。您的情况是这样的:计算C(template
绑定)依赖于计算B(data
)和可观察A(name
),计算B依赖于可观察A。当A更改,它更新B和C.当B更新时,它也会更新C.所以这就是C获得两次更新的原因。
作为参考,这里是jsFiddle中的示例,显示了两个更新:http://jsfiddle.net/mbest/DnY9V/
Knockout的节流扩展器是防止多次更新的唯一内置方法。您可以创建一个自定义绑定,它包装模板绑定以在受限制的计算可观察对象中运行更新。
ko.bindingHandlers.throttledTemplate = {
init: function(element) {
var args = arguments, self = this,
result = ko.bindingHandlers.template.init.apply(this, arguments);
ko.computed(function() {
ko.bindingHandlers.template.update.apply(self, args);
}, null, {disposeWhenNodeIsRemoved: element}).extend({throttle:1});
return result;
}
};
http://jsfiddle.net/mbest/j5D6p/
或者,您可以使用我的Deferred Updates插件来阻止对计算的可观察量的所有重复更新:https://github.com/mbest/knockout-deferred-updates