Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/templates/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 淘汰模板:afterRender触发两次,因为名称/数据是耦合的可观察对象_Javascript_Templates_Knockout.js - Fatal编程技术网

Javascript 淘汰模板: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更改都会

我无法让afterRender准确触发一次。我看到afterRender被触发了两次,因为我的模板绑定中有两个可观察对象同时更新:

<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
    更改时重新计算
    数据
    ),仍应触发模板绑定两次
我正在考虑在每个HTML模板中完全删除数据对象,附加一个带有直接绑定到modelA、modelB和modelC的
,但是如果数据发生更改,我就不会得到这些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;
    }
};