Я только начинаю работать с 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.Есть ли способ отсрочить этот повторный вызов, или, возможно, вставить все мои элементы сразу?
Я могу добавить больше кода, если это необходимо, но я уверен, что это то, что имеет значение.По большей части я просто следовал инструкциям по нокауту с сайта.
ОБНОВЛЕНИЕ:
Согласно приведенному ниже совету, я обновил свой код:
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 секунд.Это кажется лучшим подходом, если не считать решения, которое бы динамически загружало больше данных при прокрутке.