2 votes

Knockout.js - Arrêter le rerendering des éléments dans la boucle foreach

Sur mon viewModel, j'ai un tableau observable appelé "bays", qui contient un ou plusieurs objets "bay". Chaque objet "bay" contient ensuite un tableau observable appelé "products", qui peut contenir des objets "product". Mon balisage ressemble à ce qui suit

<div data-bind="foreach: bays">
    <div class="bay" data-bind="foreach: products">
        <div class="product">
        <!-- Product innards -->
        </div>
    </div>
</div>

Si l'objet produit est déplacé d'une baie à l'autre, l'élément produit, et tout ce qu'il contient, semble être détruit puis recréé, comme on peut le voir dans cette jfiddle : http://jsfiddle.net/mXyzs/20/

Comme mon application peut déplacer des centaines de produits entre les baies à la fois et qu'elle doit tous les recréer, cela pose un problème de performance. Y a-t-il un moyen pour que knockout puisse réutiliser les produits html existants, étant donné que l'objet qui les supporte ne change pas, plutôt que de détruire les éléments de produits et de les recréer tous ?

1voto

Michael Best Points 9033

Depuis la version 2.2.0 de Knockout, la fonction foreach détectera les éléments déplacés et ne redessinera pas l'interface utilisateur pour ces éléments. Mais dans votre cas, vous déplacez des éléments d'un tableau à un autre, donc cette optimisation ne s'applique pas (puisque c'est seulement pour un seul foreach ).

Pour tirer parti de foreach nous pouvons aplatir la structure en un seul tableau.

var result = [];
ko.utils.arrayForEach(viewModel.bays(), function(bay) {
    ko.utils.arrayForEach(bay.products(), function(product) {
        product.bay(bay);
        result.push(product);
    });
});

Si nous utilisons un computed pour la liste aplatie, nous pouvons y faire référence dans un seul fichier foreach de la reliure.

<div data-bind="foreach: flattenedProducts">
    <div class="product">
    <!-- Product innards -->
    </div>
</div>

Avec cette méthode, bien que les produits soient triés par baie, tous les produits sont classés par ordre alphabétique. div seront des frères et sœurs. Vous ne pourrez donc pas avoir d'enfant. div par travée.

Ejemplo: http://jsfiddle.net/mbest/3ZUxZ/

0voto

Sujesh Arukil Points 2449

À première vue, l'élément produit n'est PAS recréé. J'ai ajouté une propriété créée à votre objet produit

var product = function (data) {
    this.name = ko.observable(data.name);  
    this.created = new Date();
};

Lorsque l'on clique sur le bouton Move to bay, la date de création ne semble pas changer. Elle est simplement ajoutée à un autre tableau observable et cet élément est peint.

Il y a une chose que je n'oublierai pas. Si vous faites ce push vers un tableau abservable ou ce pop à partir d'un tableau observable dans une boucle ou quelque chose comme ça, c'est coûteux et vous aurez un problème de performance.

Ryan Neimeyer en parle ici http://www.knockmeout.net/2012/04/knockoutjs-performance-gotcha.html

J'espère que cela vous aidera ! Je vous remercie ! Suj

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X