【发布时间】: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 - 非常感谢您提供的好信息。如果您愿意将其复制到答案中,我很乐意将其标记为已接受。