Dopiero zaczynam pracę z Knockout.js (zawsze chciałem go wypróbować, ale teraz w końcu mam wymówkę!) - Jednak napotykam naprawdę złe problemy z wydajnością, gdy wiążę tabelę ze stosunkowo małym zestawem dane (około 400 wierszy).
W moim modelu mam następujący kod:
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!
}
};
Problem polega na tym, że for
powyższa pętla zajmuje około 30 sekund z około 400 rzędami. Jeśli jednak zmienię kod na:
this.loadData = function (data)
{
var testArray = []; //<-- Plain ol' Javascript array
for(var i = 0; i < data.length; i++)
{
testArray.push(new ResultRow(data[i]));
}
};
Następnie for
pętla kończy się w mgnieniu oka. Innymi słowy, push
metoda obiektu Knockout observableArray
jest niesamowicie powolna.
Oto mój szablon:
<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>
Moje pytania:
- Czy to właściwy sposób na powiązanie moich danych (pochodzących z metody AJAX) z obserwowalną kolekcją?
- Spodziewam się, że za
push
każdym razem, gdy to nazywam, wykonuję ciężkie ponowne obliczenia, na przykład może odbudować powiązane obiekty DOM. Czy istnieje sposób, aby opóźnić to ponowne obliczenie lub wrzucić wszystkie moje elementy jednocześnie?
W razie potrzeby mogę dodać więcej kodu, ale jestem prawie pewien, że jest to istotne. Przez większość czasu po prostu śledziłem samouczki Knockout z witryny.
AKTUALIZACJA:
Zgodnie z poniższą radą zaktualizowałem swój kod:
this.loadData = function (data)
{
var mappedData = $.map(data, function (item) { return new ResultRow(item) });
this.projects(mappedData);
};
Jednak this.projects()
nadal trwa około 10 sekund dla 400 wierszy. Przyznaję, że nie jestem pewien, jak szybko byłoby to bez Knockout (po prostu dodając wiersze przez DOM), ale mam wrażenie, że potrwa to znacznie szybciej niż 10 sekund.
AKTUALIZACJA 2:
Zgodnie z innymi wskazówkami poniżej, dałem ujęcie jQuery.tmpl (który jest natywnie obsługiwany przez KnockOut), a ten silnik szablonów narysuje około 400 wierszy w nieco ponad 3 sekundy. Wydaje się, że jest to najlepsze podejście, bez rozwiązania, które dynamicznie ładowałoby więcej danych podczas przewijania.