Javascript 淘汰模板:afterRender触发两次,因为名称/数据是耦合的可观察对象
我无法让afterRender准确触发一次。我看到afterRender被触发了两次,因为我的模板绑定中有两个可观察对象同时更新:Javascript 淘汰模板:afterRender触发两次,因为名称/数据是耦合的可观察对象,javascript,templates,knockout.js,Javascript,Templates,Knockout.js,我无法让afterRender准确触发一次。我看到afterRender被触发了两次,因为我的模板绑定中有两个可观察对象同时更新: <div data-bind="template: { name: template.name(), data: template.data, if: template.data, afterRender: doSomeStuff }"> </div> 我试图做的是记录模板呈现的时间。我还担心两次渲染的潜在性能影响-是否每次name更改都会
<div data-bind="template: { name: template.name(), data: template.data, if: template.data, afterRender: doSomeStuff }">
</div>
我试图做的是记录模板呈现的时间。我还担心两次渲染的潜在性能影响-是否每次name
更改都会创建两次模板中的DOM元素
data
可以在不更改name
的情况下更改(例如modelA、modelB或modelC对象更改),我确实希望data
更改在其自身更改后触发afterRender。理想情况下,我可以将名称数据更新耦合到触发afterRender
一次,但我不确定这是否可行
有没有一种优雅的方式来实现这一点
- 我查看了油门延长器,但这些并不能阻止 模板绑定不会被触发两次
在推迟评估
计算的可观测数据似乎不会导致模板 当数据
更改(未更改)时绑定以拾取新对象 如果这是因为模板绑定实际上不是 当template.name
更改时重新计算template.name
),仍应触发模板绑定两次数据
的,但是如果数据发生更改,我就不会得到这些afterRender更新
编辑:我正在使用KO 2.2.1,并且意识到模板名称是不可观察的(直到2.3.0),因此在template.name后面加上括号。所以我最初的假设是,这个后渲染发生了两次,因为名称也是可观察的,这一定是错误的 绑定使用跟踪任何依赖项更改的计算可观察项进行更新。您的情况是这样的:计算的C(模板
绑定)依赖于计算的B(数据
)和可观察的A(名称
),计算的B依赖于可观察的A。当A改变时,它更新B和C。当B更新时,它也更新C。这就是为什么C得到两个更新
作为参考,以下是您在JSFIDLE中的示例,其中显示了两个更新:
节流扩展器
Knockout的throttle extender是防止多次更新的唯一内置方法。您可以创建一个自定义绑定,该绑定包装模板绑定,以在限制的计算可观察对象中运行更新
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;
}
};
延迟更新插件
或者,您可以使用“我的延迟更新”插件,该插件可防止对计算的观测值进行所有重复更新:
不幸的是,目前这不是一个选项,但如果我现在找不到有效的解决方案,我会记住这一点作为未来的解决方案。您是指这种改进:“给定元素上的绑定现在独立更新”()吗?实际上,敲除3.0在这种情况下没有帮助,因为它是单个绑定,模板
。我刚刚更新了我的JSFIDLE示例,使用2.2.1而不是3.0.0,以表明它们仍然适用。
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;
}
};