Sto appena iniziando con Knockout.js (ho sempre voluto provarlo, ma ora ho finalmente una scusa!) - Tuttavia, sto riscontrando dei problemi di prestazioni davvero brutti quando associo una tabella a un insieme relativamente piccolo di dati (circa 400 righe circa).
Nel mio modello ho il seguente codice:
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!
}
};
Il problema è che il for
ciclo sopra richiede circa 30 secondi circa con circa 400 righe. Tuttavia, se cambio il codice in:
this.loadData = function (data)
{
var testArray = []; //<-- Plain ol' Javascript array
for(var i = 0; i < data.length; i++)
{
testArray.push(new ResultRow(data[i]));
}
};
Quindi il for
ciclo si completa in un batter d'occhio. In altre parole, il push
metodo observableArray
dell'oggetto Knockout è incredibilmente lento.
Ecco il mio modello:
<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>
Le mie domande:
- È questo il modo giusto per associare i miei dati (che provengono da un metodo AJAX) a una raccolta osservabile?
- Mi aspetto che
push
esegua un pesante ricalcolo ogni volta che lo chiamo, come forse la ricostruzione di oggetti DOM associati. C'è un modo per ritardare questo ricalcolo o forse inserire tutti i miei elementi contemporaneamente?
Posso aggiungere altro codice se necessario, ma sono abbastanza sicuro che questo sia ciò che è rilevante. Per la maggior parte stavo solo seguendo i tutorial di Knockout dal sito.
AGGIORNARE:
Per i consigli seguenti, ho aggiornato il mio codice:
this.loadData = function (data)
{
var mappedData = $.map(data, function (item) { return new ResultRow(item) });
this.projects(mappedData);
};
Tuttavia, this.projects()
occorrono ancora circa 10 secondi per 400 righe. Ammetto di non essere sicuro di quanto sarebbe veloce senza Knockout (aggiungendo solo righe attraverso il DOM), ma ho la sensazione che sarebbe molto più veloce di 10 secondi.
AGGIORNAMENTO 2:
Per altri consigli di seguito, ho dato una possibilità a jQuery.tmpl (che è supportato nativamente da KnockOut) e questo motore di modelli disegnerà circa 400 righe in poco più di 3 secondi. Questo sembra l'approccio migliore, a parte una soluzione che caricherà dinamicamente più dati durante lo scorrimento.