Comprendre l'expression ngRepeat 'track by'

101

J'ai du mal à comprendre comment fonctionne la piste par expression de ng-repeat dans angularjs. La documentation est très rare: http://docs.angularjs.org/api/ng/directive/ngRepeat

Pouvez-vous expliquer quelle est la différence entre ces deux extraits de code en termes de liaison de données et d'autres aspects pertinents?

avec: track by $index

<!--names is an array-->
<div ng-repeat="(key, value) in names track by $index">
  <input ng-model="value[key]">                         
</div>

sans (même sortie)

<!--names is an array-->
<div ng-repeat="(key, value) in names">
   <input ng-model="value[key]">                         
</div>
Jonathan Grupp
la source
Une excellente question, avec de très bonnes réponses! Quel dommage que le PO n'ait pas accepté de réponse - ou ne pensez-vous pas que la question a été correctement répondue?
Mawg dit de réintégrer Monica le
Vous avez raison! Je viens d'accepter la réponse de TJ.
Jonathan Grupp

Réponses:

96

Vous pouvez track by $indexsi votre source de données a des identifiants en double

par exemple: $scope.dataSource: [{id:1,name:'one'}, {id:1,name:'one too'}, {id:2,name:'two'}]

Vous ne pouvez pas parcourir cette collection en utilisant «id» comme identifiant (id en double: 1).

NE FONCTIONNE PAS:

<element ng-repeat="item.id as item.name for item in dataSource">
  // something with item ...
</element>

mais vous pouvez, si vous utilisez track by $index:

<element ng-repeat="item in dataSource track by $index">
  // something with item ...
</element>
nilsK
la source
1
Merci pour votre réponse! Mais les identifiants en double ne sont certainement pas le seul cas d'utilisation. J'aimerais aussi savoir ce qui se passe «sous le capot».
Jonathan Grupp
2
eh bien, c'est facile: il suffit de jeter un œil au code , tout est open source;)
nilsK
4
Cette question est ancienne mais je pense toujours que cela pourrait aider à mieux comprendre bennadel.com/blog/… version courte de l'explication ici docs.angularjs.org/error/ngRepeat/dupes
Annapoorni D
3
Une autre chose à prendre en compte est que si vous pouvez utiliser piste par clé, vous obtiendrez de meilleures performances (blog.500tech.com/is-reactjs-fast). Cette fonctionnalité vous permet d'associer un objet JavaScript à un nœud DOM (Document Object Model) ngRepeat à l'aide d'un identifiant unique. Avec cette association en place, AngularJS ne détruira pas et ne recréera pas les nœuds DOM inutilement. Cela peut avoir un énorme avantage en termes de performances et d'expérience utilisateur ( bennadel.com/blog/… ).
Braulio
J'ai une liste de 700 articles impairs. Le temps de rendu est passé de 4 secondes à 100 ms. Track by doit être utilisé pour tous les ngRepeat en fonction des données provenant du repos.
Patrick
60

un bref résumé:

track by est utilisé afin de lier vos données avec la génération DOM (et principalement la re-génération) faite par ng-repeat.

lorsque vous ajoutez, track byvous dites essentiellement à angular de générer un seul élément DOM par objet de données dans la collection donnée

cela peut être utile lors de la pagination et du filtrage, ou dans tout cas où des objets sont ajoutés ou supprimés de la ng-repeatliste.

généralement, sans track byangular, il liera les objets DOM avec la collection en injectant une propriété expando - $$hashKey- dans vos objets JavaScript, et le régénérera (et réassociera un objet DOM) à chaque modification.

explication complète:

http://www.bennadel.com/blog/2556-using-track-by-with-ngrepeat-in-angularjs-1-2.htm

un guide plus pratique:

http://www.codelord.net/2014/04/15/improving-ng-repeat-performance-with-track-by/

(track by est disponible en angulaire> 1.2)

Nuriel
la source
8

Si vous travaillez avec des objets suivis par l'identifiant (par exemple $ index) au lieu de l'objet entier et que vous rechargez vos données plus tard, ngRepeat ne reconstruira pas les éléments DOM pour les éléments qu'il a déjà rendus , même si les objets JavaScript de la collection ont remplacé par de nouveaux.

ram1993
la source
une référence qui le prouve?
azerafati
existe-t-il un moyen de forcer le re-rendu? ou tout autre travail autour? Je n'ai trouvé cela mentionné nulle part mais je crois que c'est ce qui crée un désordre pour moi et j'ai déjà perdu beaucoup de temps.
NeverGiveUp161
1
n'utilisez pas le suivi ou ne modifiez pas l'identifiant unique lors du changement d'objet. Notez que vous ne pouvez pas changer $ index, il est recommandé de ne pas utiliser $ index à la place, utilisez l'identifiant unique de l'objet (par exemple, id)
ram1993