Je ne fais que commencer avec Knockout.js (j'ai toujours voulu l'essayer, mais maintenant j'ai enfin une excuse!) - Cependant, je rencontre de très mauvais problèmes de performances lors de la liaison d'une table à un ensemble relativement petit de données (environ 400 lignes environ).
Dans mon modèle, j'ai le code suivant:
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!
}
};
Le problème est que la for
boucle ci-dessus prend environ 30 secondes environ avec environ 400 lignes. Cependant, si je change le code en:
this.loadData = function (data)
{
var testArray = []; //<-- Plain ol' Javascript array
for(var i = 0; i < data.length; i++)
{
testArray.push(new ResultRow(data[i]));
}
};
Ensuite, la for
boucle se termine en un clin d'œil. En d'autres termes, la push
méthode de l' observableArray
objet de Knockout est incroyablement lente.
Voici mon modèle:
<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>
Mes questions:
- Est-ce la bonne façon de lier mes données (qui proviennent d'une méthode AJAX) à une collection observable?
- Je m'attends à
push
faire un recalcul lourd à chaque fois que je l'appelle, comme peut-être la reconstruction d'objets DOM liés. Existe-t-il un moyen de retarder ce recalcul, ou peut-être d'insérer tous mes articles en même temps?
Je peux ajouter plus de code si nécessaire, mais je suis presque sûr que c'est ce qui est pertinent. Pour la plupart, je ne faisais que suivre les didacticiels Knockout du site.
MISE À JOUR:
Selon les conseils ci-dessous, j'ai mis à jour mon code:
this.loadData = function (data)
{
var mappedData = $.map(data, function (item) { return new ResultRow(item) });
this.projects(mappedData);
};
Cependant, this.projects()
prend encore environ 10 secondes pour 400 lignes. J'admets que je ne sais pas à quelle vitesse ce serait sans Knockout (juste en ajoutant des lignes via le DOM), mais j'ai le sentiment que ce serait beaucoup plus rapide que 10 secondes.
MISE À JOUR 2:
Par autre conseil ci-dessous, j'ai donné un coup de feu à jQuery.tmpl (qui est nativement pris en charge par KnockOut), et ce moteur de création de modèles dessinera environ 400 lignes en un peu plus de 3 secondes. Cela semble être la meilleure approche, à l'exception d'une solution qui chargerait dynamiquement plus de données lorsque vous faites défiler.