這樣的事情呢?說,你有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