【问题标题】:KnockoutJS - if binding performanceKnockoutJS - 如果绑定性能
【发布时间】:2012-10-01 18:12:44
【问题描述】:

我有一个包含 50 个项目的可观察数组,使用 foreach 绑定呈现。

我试图理解为什么每个项目呈现的模板都受到if 绑定的影响。本质上,我是基于计算的 observable 显示或隐藏我的模板的一大块。这让我觉得渲染时间增加了 70-100%(与使用 visible 绑定相比)。

Ryan Niemeyer 的 great post on this topic 表示将计算值绑定到 if 绑定将导致所有内容在每次计算值的任何部分更新时重新呈现。但是我计算的 不会 在 observable 数组被循环遍历期间改变值。

this.filtersAvailable = ko.computed(function () { 
   return this.searchInfo.searchType() != 'invites' && this.searchInfo.searchType() != 'requests' 
}, this);

为了确保它实际上没有改变,我添加了这个:

this.filtersAvailable.subscribe(function(newVal) { alert("fa" + newVal); });
this.searchInfo.searchType.subscribe(function(newVal) { alert("st" + newVal); });

也就是说,这个计算的 定义在比我的可观察数组的单个视图模型更高的级别上,并且在我的模板中的其他位置都被重复调用,当然还有我的可观察数组中的所有其他项目。

计算的 observable 的这种重复调用是否会导致通过if 绑定绑定到它的事物重新渲染?

【问题讨论】:

  • 也许你可以在 jsFiddle 中得到一个简化的重现?一次又一次地访问计算出的 observable 的值不是问题,因为每次都取回缓存的值。听起来您的订阅没有显示频繁更新?即使值相同,计算也会如此。您可以尝试在您的if 部分中添加​<div data-bind="text: Date()"></div>​​​​​​​​​​​​​​​​​​​​​,看看日期更新是否比您预期的更频繁。
  • @RPN - 我添加了一个<span data-bind="text: new Date().getTime()"></span>,果然,当我滚动渲染项目列表时,这些值都在向上移动。如果不断地重新渲染它们,我希望它们都(大约)相同,对吧?这不是问题,因为我可以使用visible;我只是想弄清楚问题是什么,所以我希望能学到一些东西。所以你的意思是,如果底层的 observables 不经常更新,那么 foreach 内部的 if 绑定就不会必然成为问题?
  • 是的,如果一切都被一次又一次地重新渲染,那么日期可能会接近相同。对于值为真值的情况,if 绑定的开销稍大一些,因为它获取子元素的副本,然后将副本呈现为模板并绑定它。 visible 只会设置 display 样式。现在,if 绑定可以在初始值可能为 false 并且隐藏部分中有很多标记/绑定的情况下为您提供更好的性能。 if 甚至不会渲染它们,而 visible 仍然会绑定,但只是隐藏。
  • 您也可以尝试使用命名模板,其中有您的if。如果您在foreach 内执行if,则KO 必须在每个foreach 项目内一次又一次地将子元素复制为模板。你可以做<div data-bind="template: { name: 'subItemTmpl', 'if': myFlag, data: subData"></div>
  • @RPN - 非常感谢您提供的好信息。如果您愿意将其复制到答案中,我很乐意将其标记为已接受。

标签: knockout.js knockout-2.0


【解决方案1】:

一次又一次地访问计算出的 observable 的值不是问题,因为您每次都会取回缓存的值。听起来您的订阅没有显示频繁更新?

如果值相同,即使是计算的也会如此。您可以尝试在if 部分中添加一个​<div data-bind="text: Date()"></div>​​​​​​​​​​​​​​​​​​​​​,看看日期更新是否比您预期的更频繁。

如果一切都一次又一次地重新渲染,那么日期可能会接近相同。对于值为真值的情况,if 绑定的开销稍大一些,因为它获取子元素的副本,然后将副本呈现为模板并对其进行绑定。 visible 只会设置显示样式。现在,如果初始值可能为假并且隐藏部分中有很多标记/绑定,if 绑定可以为您提供更好的性能。 if 甚至不会渲染它们,而 visible 仍然会绑定,但只是隐藏。

您也可以尝试使用命名模板,其中包含您的 if。如果您在foreach 内执行if,则KO 必须在每个foreach 项内一次又一次地将子元素复制为模板。你可以做<div data-bind="template: { name: 'subItemTmpl', 'if': myFlag, data: subData"></div>

【讨论】:

    【解决方案2】:

    如果不查看更多代码,就很难对问题所在形成一个好主意。但是通过使用最新的候选版本 Knockout,您可能会看到改进,其中包括对 if 绑定的优化,以消除不必要的重新渲染。可通过https://github.com/SteveSanderson/knockout/downloads 下载。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2015-05-27
      • 2013-09-02
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-03-30
      • 2012-05-05
      相关资源
      最近更新 更多