【发布时间】:2012-03-31 08:23:35
【问题描述】:
我刚刚开始使用 Knockout.js(一直想尝试一下,但现在我终于有了一个借口!) - 但是,在将表绑定到相对少量数据(大约 400 行左右)。
在我的模型中,我有以下代码:
this.projects = ko.observableArray( [] ); //Bind to empty array at startup
this.loadData = function (data) //Called when AJAX method returns
{
for(var i = 0; i < data.length; i++)
{
this.projects.push(new ResultRow(data[i])); //<-- Bottleneck!
}
};
问题是上面的for 循环大约需要 30 秒左右,大约有 400 行。但是,如果我将代码更改为:
this.loadData = function (data)
{
var testArray = []; //<-- Plain ol' Javascript array
for(var i = 0; i < data.length; i++)
{
testArray.push(new ResultRow(data[i]));
}
};
然后for 循环在眨眼之间完成。换句话说,Knockout 的observableArray 对象的push 方法非常慢。
这是我的模板:
<tbody data-bind="foreach: projects">
<tr>
<td data-bind="text: code"></td>
<td><a data-bind="projlink: key, text: projname"></td>
<td data-bind="text: request"></td>
<td data-bind="text: stage"></td>
<td data-bind="text: type"></td>
<td data-bind="text: launch"></td>
<td><a data-bind="mailto: ownerEmail, text: owner"></a></td>
</tr>
</tbody>
我的问题:
- 这是将我的数据(来自 AJAX 方法)绑定到可观察集合的正确方法吗?
- 我希望
push每次调用它时都会进行一些繁重的重新计算,例如可能重建绑定的 DOM 对象。有没有办法延迟重新计算,或者一次推送我的所有项目?
如果需要,我可以添加更多代码,但我很确定这是相关的。在大多数情况下,我只是关注网站上的 Knockout 教程。
更新:
根据以下建议,我更新了我的代码:
this.loadData = function (data)
{
var mappedData = $.map(data, function (item) { return new ResultRow(item) });
this.projects(mappedData);
};
但是,this.projects() 对于 400 行仍然需要大约 10 秒。我承认我不确定 没有 Knockout(只是通过 DOM 添加行)会有多快,但我感觉它会比 10 秒快得多。
更新 2:
根据下面的其他建议,我尝试了 jQuery.tmpl(KnockOut 原生支持),这个模板引擎将在 3 秒多的时间内绘制大约 400 行。这似乎是最好的方法,缺少一种在您滚动时动态加载更多数据的解决方案。
【问题讨论】:
-
您是使用淘汰赛foreach 绑定还是使用foreach 的模板绑定。我只是想知道使用模板并包含 jquery tmpl 而不是本机模板引擎是否会有所作为。
-
@MikeChristensen - Knockout 拥有自己的与 (foreach, with) 绑定相关的本机模板引擎。它还支持其他模板引擎,即 jquery.tmpl。阅读here 了解更多详情。我没有对不同的引擎进行任何基准测试,所以不知道它是否会有所帮助。阅读您之前的评论,在 IE7 中您可能很难获得您所追求的性能。
-
考虑到我们几个月前刚刚获得 IE7,我认为 IE9 将在 2019 年夏天左右推出。哦,我们也都在使用 WinXP.. Blech。
-
p.s.,看起来很慢的原因是您要向该可观察数组单独添加 400 个项目。对于可观察对象的每次更改,都必须为依赖于该数组的任何内容重新渲染视图。对于复杂的模板和许多要添加的项目,当您可以通过将数组设置为不同的实例来一次更新数组时,这会产生很多开销。至少在那时,重新渲染将完成一次。
-
我找到了一种更快、更整洁的方法(没有开箱即用)。使用
valueHasMutated就可以了。如果你有时间,请检查答案。
标签: javascript performance knockout.js