Я тільки починаю роботу з 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
петля завершується у мить ока. Іншими словами, push
метод об'єкта "Нокаут" observableArray
неймовірно повільний.
Ось мій шаблон:
<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. Чи є спосіб або затримати цей повторний повтор, або, можливо, всунути всі мої предмети відразу?
Я можу додати більше коду, якщо це потрібно, але я впевнений, що саме це є важливим. Здебільшого я просто дотримувався навчальних посібників з нокауту на сайті.
ОНОВЛЕННЯ:
Відповідно до наведених нижче порад, я оновив свій код:
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), і цей механізм шаблонування намалює близько 400 рядків лише за 3 секунди. Це здається найкращим підходом, за винятком рішення, яке динамічно завантажує більше даних під час прокрутки.