AngularJS 'ng-filtre" est très lent sur le tableau de ~1000 éléments
J'ai un simple <input>
filtre de recherche mis en place pour une liste de itemnames dans AngularJS
.
Ma liste ressemble à ceci:
var uniqueLists = {
category1: ['item1', 'item2', 'item3' ... 'item180' ], //Real list contains ~180 items
category2: ['itemA', 'itemB', 'itemC' ... 'itemZZZ' ], //Real list contains ~1080 items
category3: ['otheritem1', 'otheritem2', 'otheritem3' ] //Real list contains 6 items
}
Je itérer sur cette liste Angulaire et d'imprimer les résultats dans un <ul>
pour chaque catégorie.
<div ng-repeat="(key,val) in uniqueLists">
<form ng-model="uniqueLists[index][0]">
<input ng-model="searchFilter" type="text" />
<ul>
<li ng-repeat="value in val | filter: searchFilter">
<label>
<input type="checkbox" ng-model="selectedData[key][value]" />
{{value}}
</label>
</li>
</ul>
</form>
</div>
Pour plus de clarté, selectedData ressemble à ceci:
var selectedData = {category1: [item1:true], category2: [], category3: []); //if 'item1's checkbox is checked.
Cette liste est fonctionne très bien, bien que la filter
est assez lag, même sur mon très-rapide de l'ordinateur. Taper une lettre dans l'entrée dure 1 à 2 secondes pour que la liste soit mise à jour.
Je suis conscient que c'est probablement parce que je suis le filtrage par environ 1000 éléments à la fois, mais je n'ai pas vu de discussion de cet ailleurs.
Est-il possible d'obtenir de meilleures performances du filtre?
- Un jsfiddle avec votre code allez vraiment vous aider dans ce cas. Aussi j'imagine que le fait d'avoir une boucle dans une boucle, puis le filtre est tout à fait bien, u avez également la création d'une forme à l'intérieur de la première boucle. Un jsffidle allons vraiment nous aider à vous aider 😉
Vous devez vous connecter pour publier un commentaire.
Le principal problème avec le filtre approche est que, lors de chaque modification du dom est manipulé, donc ce n'est pas le filtre qui est lent mais les conséquences. Une alternative est d'utiliser quelque chose comme:
sur la répétition de l'élément.
De prêt du code de @excès de Zèle, vous pouvez utiliser les éléments suivants pour comparer le comportement:
Mise à jour: Angulaire v1.2 a la
track by
de la syntaxe. Ce qui contribue aussi à de tels problèmes. Fourni les éléments ont une certaine attribut unique, on peut utiliser:Où
item.id
doit être unique dans tous les éléments. Avectrack by
seulement ceux des dom-éléments seront supprimés qui ne sont plus dans la liste finale, les autres seront rappeler. Alors que sanstrack by
l'ensemble de la liste est redessiné à chaque fois. En bref: beaucoup moins de manipulation du dom = plus rapide redessiner.ng-repeat="item in items | filter:searchFilter track by item.id"
Cela a conduit à exactement 0 augmentation de la performance. Mes données était déjà en forme d'objet, avec des valeurs uniques, en ajoutanttrack by depot.val
fait absolument aucune différence. Ai-je raté quelque chose?Un autre élément intéressant de l'optimisation est de "ne pas déclencher" le changement de modèle jusqu'à un certain temps.
En ajoutant ceci à votre champ de saisie de recherche: ng-modèle-options="{anti-rebond: 500}"
Cela va déclencher le filtre si l'utilisateur arrêtez de taper pendant 500ms.
J'ai mis à jour la au-dessus de violon:
http://jsfiddle.net/CXBN4/14/
J'ai créé un violon à simuler (en partie) du code de vous montrer.
Sur mon ordinateur, qui est rapide, mais pas super rapide, qui fonctionne de façon acceptable. C'est un peu lent, mais c'est le filtrage d'une trop longue liste qui a les deux sens de la liaison avec les cases à cocher. Chaque fois que vous tapez une lettre, l'ensemble de la liste doivent être scannés et les éléments supprimés (ou ajouté).
Je pense que votre meilleur pari pour la résolution de ce est pour ajouter une sorte de simple pagination, comme indiqué dans cette StackOverflow réponse.
Ici, j'ai modifié mon exemple pour inclure la pagination. Vous aurez probablement envie d'investir dans une meilleure solution que de simplement Suivant /Précédent, mais cela vous montre comment le résultat peut être très rapide si vous ne présentez pas de tout à la fois. Il se cherche encore l'ensemble de la liste, mais la liste est beaucoup plus limitée.
Les ajouts:
Ajouter la pagination info à la portée dans le contrôleur:
Créer un nouveau filtre pour démarrer à partir d'une page spécifique:
Ajouter des filtres à la vue de limiter la liste:
Ajouter des boutons de pagination à la page:
Chaque fois que vous appuyez sur la touche à l'entrée de toutes les regarder expressions doivent être exécutés et en regardant votre code, vous avez beaucoup d'entre eux.
Si les noms d'éléments sont immuables vous pouvez utiliser par exemple https://github.com/abourget/abourget-angular qui vous permet d'écrire:
Et vous avez moins de 1000 regarder les expressions à exécuter sur chaque frappe.
En plus, vous pouvez utiliser une certaine forme de limitation sur entrée afin de filtre déclenche après 500ms de la dernière touche.
Vous pouvez également limiter le nombre d'éléments qui seront affichés à l'aide d'un "limitTo" du filtre. Cela vous permet de toujours avoir un grand nombre d'articles dans votre modèle que vous êtes de filtrage, mais il ne sera pas aussi lent parce que vous n'êtes pas en essayant de montrer TOUS les éléments dans le DOM.
Ici est une version modifiée de jsbin basé sur les réponses précédentes, mais avec le limitTo filtre appliqué:
http://jsbin.com/IhOcaKo/1
Pas de solutions de travail pour moi 🙁
Enfin je RÉSOLU le problème de cette façon, il vous suffit de:
viens de l'essayer et obtenir de l'résolu... 🙂