Knockout.js невероятно медленно работает с полубольшими наборами данных - PullRequest
86 голосов
/ 15 марта 2012

Я только начинаю работать с 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>

Мои вопросы:

  1. Является ли это правильным способом связать мои данные (получаемые из метода AJAX) с наблюдаемой коллекцией?
  2. Я ожидаю, что 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 секунд.Это кажется лучшим подходом, если не считать решения, которое бы динамически загружало больше данных при прокрутке.

Ответы [ 12 ]

0 голосов
/ 01 марта 2016

Если вы используете IE, попробуйте закрыть инструменты разработчика.

Открытие инструментов разработчика в IE значительно замедляет эту операцию. Я добавляю ~ 1000 элементов в массив. Когда инструменты разработки открыты, это занимает около 10 секунд, и IE зависает, пока это происходит. Когда я закрываю инструменты разработки, операция происходит мгновенно, и я не вижу замедления в IE.

0 голосов
/ 29 июля 2014

Я также заметил, что шаблонный движок Knockout js работает медленнее в IE, я заменил его на underscore.js, работает намного быстрее.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...