Grundlegendes zum ngRepeat-Ausdruck "Track by"

101

Ich habe Schwierigkeiten zu verstehen, wie die Spur durch Ausdruck von ng-repeat in anglejs funktioniert. Die Dokumentation ist sehr knapp: http://docs.angularjs.org/api/ng/directive/ngRepeat

Können Sie erklären, was der Unterschied zwischen diesen beiden Codeausschnitten in Bezug auf die Datenbindung und andere relevante Aspekte ist?

mit: track by $index

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

ohne (gleiche Ausgabe)

<!--names is an array-->
<div ng-repeat="(key, value) in names">
   <input ng-model="value[key]">                         
</div>
Jonathan Grupp
quelle
Eine tolle Frage mit sehr guten Antworten! Wie schade, dass das OP keine Antwort akzeptiert hat - oder glauben Sie nicht, dass die Frage richtig beantwortet wurde?
Mawg sagt, Monica
Du hast recht! Ich habe gerade TJs Antwort akzeptiert.
Jonathan Grupp

Antworten:

96

Sie können, track by $indexwenn Ihre Datenquelle doppelte Bezeichner hat

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

Sie können diese Sammlung nicht iterieren, während Sie 'id' als Bezeichner verwenden (doppelte ID: 1).

WIRD NICHT ARBEITEN:

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

aber Sie können, wenn Sie verwenden track by $index:

<element ng-repeat="item in dataSource track by $index">
  // something with item ...
</element>
nilsK
quelle
1
Danke für deine Antwort! Aber sicherlich sind doppelte Bezeichner nicht der einzige Anwendungsfall. Außerdem würde ich gerne wissen, was "unter der Haube" passiert.
Jonathan Grupp
2
Nun
4
Diese Frage ist alt, aber ich denke immer noch, dass dies helfen könnte, viel besser zu verstehen. Bennadel.com/blog/… Kurzversion der Erklärung hier docs.angularjs.org/error/ngRepeat/dupes
Annapoorni D
3
Eine weitere zu berücksichtigende Sache ist, dass Sie eine bessere Leistung erzielen, wenn Sie Track by Key verwenden können (blog.500tech.com/is-reactjs-fast). Mit dieser Funktion können Sie ein JavaScript-Objekt mithilfe einer eindeutigen Kennung einem ngRepeat DOM-Knoten (Document Object Model) zuordnen. Mit dieser Zuordnung wird AngularJS DOM-Knoten nicht unnötig zerstören und neu erstellen. Dies kann einen enormen Vorteil in Bezug auf Leistung und Benutzererfahrung haben ( bennadel.com/blog/… ).
Braulio
Ich habe eine Liste von 700 ungeraden Gegenständen. Die Renderzeit stieg von 4 Sekunden auf 100 ms. Track by sollte für alle ngRepeats verwendet werden, die auf Daten basieren, die aus dem Ruhezustand stammen.
Patrick
60

eine kurze Zusammenfassung:

track by wird verwendet, um Ihre Daten mit der DOM-Generierung (und hauptsächlich der Neuerstellung) von ng-repeat zu verknüpfen.

Wenn Sie hinzufügen track by, weisen Sie angle grundsätzlich an, ein einzelnes DOM-Element pro Datenobjekt in der angegebenen Sammlung zu generieren

Dies kann nützlich sein, wenn Sie blättern und filtern oder wenn Objekte hinzugefügt oder aus der ng-repeatListe entfernt werden.

In der Regel track bywerden die DOM-Objekte ohne Winkel mit der Auflistung verknüpft, indem eine expando-Eigenschaft - $$hashKey- in Ihre JavaScript-Objekte eingefügt wird. Bei jeder Änderung wird sie neu generiert (und ein DOM-Objekt neu zugeordnet).

vollständige Erklärung:

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

eine praktischere Anleitung:

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

(Track by ist in Winkel> 1,2 verfügbar)

Nuriel
quelle
8

Wenn Sie mit Objekten arbeiten , die anhand des Bezeichners (z. B. $ index) anstelle des gesamten Objekts verfolgt werden, und Ihre Daten später neu laden, erstellt ngRepeat die DOM-Elemente für bereits gerenderte Elemente nicht neu , selbst wenn die JavaScript-Objekte in der Auflistung vorhanden sind wurde durch neue ersetzt.

ram1993
quelle
Gibt es eine Referenz, die dies beweist?
Azerafati
Gibt es eine Möglichkeit, das erneute Rendern zu erzwingen? oder irgendeine andere Lösung? Ich habe das nirgends erwähnt gefunden, aber ich glaube, das ist es, was ein Chaos für mich verursacht und ich habe bereits viel Zeit verschwendet.
NeverGiveUp161
1
Verwenden Sie entweder nicht Track by oder ändern Sie die eindeutige Kennung beim Ändern des Objekts. Beachten Sie, dass Sie $ index nicht ändern können. Es wird empfohlen, $ index nicht zu verwenden, sondern einen für das Objekt eindeutigen Bezeichner (z. B. id) zu verwenden
ram1993