Я только начинаю с 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
объекта Knockout 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. Есть ли способ либо отсрочить этот recalc, либо, возможно, нажать на все мои предметы одновременно?
Я могу добавить больше кода, если это необходимо, но я уверен, что это важно. По большей части я просто следил за учебниками Nockout с сайта.
UPDATE:
В приведенном ниже совете я обновил свой код:
this.loadData = function (data)
{
var mappedData = $.map(data, function (item) { return new ResultRow(item) });
this.projects(mappedData);
};
Тем не менее, this.projects()
по-прежнему занимает около 10 секунд для 400 строк. Я признаю, что не уверен, насколько быстро это будет без Knockout (просто добавление строк через DOM), но у меня есть ощущение, что это будет намного быстрее, чем 10 секунд.
ОБНОВЛЕНИЕ 2:
В другом совете ниже я дал jQuery.tmpl снимок (который изначально поддерживается KnockOut), и этот механизм шаблонов будет рисовать около 400 строк всего за 3 секунды. Это похоже на лучший подход, за исключением решения, которое будет динамически загружать больше данных при прокрутке.