这样的事情呢?说,你有viewModel.items = ko.observableArray()
,你想呈现。
- 有一个单独的不可观察数组的所有数据:
var itemsToRender = functionThatReturnsLargeArray()
。
- 将
itemsToRender
中的部分数据放入可观察数组中。说只有50个元素。
- 保持将元素添加到
setTimeout
回调中的可观察数组中。
注1:你可以添加一些时间跟踪到setTimeout
回调和增加/减少您添加在每次迭代的项目数。您的目标是将每个回调时间保持在50-100毫秒以下,以便您的应用程序仍能感觉到响应。
var batchSize = 50; // default number of items rendered per iteration
var batchOffset = 0;
function render(items, itemsToRender, done) {
setTimeout(function() {
var startTime = new Date().getTime();
items.pushAll(itemsToRender.slice(batchOffset, batchSize));
batchOffset += batchSize;
// at this point Knockout rendered next batchSize items from itemsToRender
var endTime = new Date().getTime();
// update batchSize for next iteration
batchSize = batchSize * 50/(endTime - startTime); // 50 milliseconds
batchSize = Math.min(itemsToRender.length, batchOffset + batchSize);
if (batchSize > 0) render() else done(); // callback if you need one
}, 0);
}
/* I haven't actually tested the code */
另一批量更新策略可以基于目标FPS。假设您希望获得60 fps的更新速率,因此每1000毫秒需要60个电话给setTimeout
。处理整个收藏需要更长的时间。您也可以使用而不是setTimeout
并查看如何解决问题。
编辑:Build-in throttling加入到Knockout JS 1.3(目前它在测试阶段,但似乎相当稳定)。
注2:如果认为其他一些数据取决于viewModel.items
你仍然可以映射下来到原数组itemsToRender
。比如说,你想显示收藏中的物品数量。如果您使用viewModel.items().length
,则最终会在UI中更改大小值,同时会渲染更多项目。为了避免这种情况,您可以首先根据itemsToRender
定义您的尺寸绑定为dependentObservable
,而不是viewModel.items
。完成渲染所有项目后,如果您觉得合适,可将其重新映射到viewModel.items
。
这将说明这个问题:http://jsfiddle.net/DESC3/10/它已经减少了数据量,因为它不需要表达点。 – Esailija
下面是如何使用不同的方法http://jsfiddle.net/DESC3/11/立即呈现相同的html(2000行)。我不是说要这样做,但它只是表明淘汰赛不是非常优化... – Esailija
@Esailija - 你的第一个例子其实很快。对于大于1000行的我们来说,这只是一个问题。同样,我们也有一些理由将所有数据都纳入其中。因此,分页或以块形式发送数据不是真正的选择。 – RyanScottLewis