Zrozumienie wyrażenia ngRepeat „track by”


102

Mam trudności ze zrozumieniem, jak działa utwór wyrażony przez wyrażenie ng-repeat w angularjs. Dokumentacja jest bardzo rzadka: http://docs.angularjs.org/api/ng/directive/ngRepeat

Czy możesz wyjaśnić, jaka jest różnica między tymi dwoma fragmentami kodu pod względem wiązania danych i innych istotnych aspektów?

z: track by $index

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

bez (to samo wyjście)

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

Świetne pytanie z bardzo dobrymi odpowiedziami! Szkoda, że ​​PO nie przyjął odpowiedzi - lub nie sądzisz, że odpowiedź na pytanie jest prawidłowa?
— Mawg mówi, że przywróć Monikę

Masz rację! Właśnie zaakceptowałem odpowiedź TJ'a.
— Jonathan Grupp,

Odpowiedzi:


97

Możesz, track by $indexjeśli źródło danych ma zduplikowane identyfikatory

na przykład: $scope.dataSource: [{id:1,name:'one'}, {id:1,name:'one too'}, {id:2,name:'two'}]

Nie możesz iterować tej kolekcji, używając „id” jako identyfikatora (zduplikowany identyfikator: 1).

NIE DZIAŁA:

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

ale możesz, jeśli używasz track by $index:

<element ng-repeat="item in dataSource track by $index">
  // something with item ...
</element>

1
Dziękuję za odpowiedź! Ale z pewnością zduplikowane identyfikatory nie są jedynym przypadkiem użycia. Chciałbym też wiedzieć, co się dzieje „pod maską”.
— Jonathan Grupp

2
cóż, to proste: wystarczy spojrzeć na kod , wszystko to jest open source;)
— nilsK

4
To pytanie jest stare, ale nadal myślę, że może pomóc lepiej zrozumieć bennadel.com/blog/ ... krótką wersję wyjaśnienia tutaj docs.angularjs.org/error/ngRepeat/dupes
— Annapoorni D

3
Jeszcze jedna rzecz, którą należy wziąć pod uwagę, to fakt, że jeśli możesz używać funkcji śledzenia według klucza, uzyskasz lepszą wydajność (blog.500tech.com/is-reactjs-fast). Ta funkcja umożliwia powiązanie obiektu JavaScript z węzłem ngRepeat DOM (Document Object Model) przy użyciu unikalnego identyfikatora. Dzięki temu powiązaniu AngularJS nie będzie niepotrzebnie niszczyć i ponownie tworzyć węzłów DOM. Może to przynieść ogromne korzyści w zakresie wydajności i wygody użytkownika ( bennadel.com/blog/… ).
— Braulio

Mam listę 700 dziwnych pozycji. Czas renderowania wzrósł z 4 sekund do 100 ms. Track by powinien być używany dla wszystkich ngRepeat na podstawie danych pochodzących z reszty.
— Patrick

60

krótkie podsumowanie:

track by jest używany w celu powiązania danych z generacją DOM (i głównie ich ponownym generowaniem) wykonaną przez ng-repeat.

kiedy dodajesz track by, w zasadzie mówisz angularowi, żeby wygenerował pojedynczy element DOM na obiekt danych w danej kolekcji

może to być przydatne podczas stronicowania i filtrowania lub w każdym przypadku, gdy obiekty są dodawane lub usuwane z ng-repeatlisty.

zazwyczaj bez track byangular łączy obiekty DOM z kolekcją, wstrzykując właściwość expando - $$hashKey- do twoich obiektów JavaScript i ponownie ją generuje (i ponownie kojarzy obiekt DOM) przy każdej zmianie.

pełne wyjaśnienie:

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

bardziej praktyczny przewodnik:

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

(śledzenie jest dostępne pod kątem> 1,2)


8

Jeśli pracujesz z obiektami śledzonymi według identyfikatora (np. $ Index) zamiast z całym obiektem i ponownie załadujesz dane później, ngRepeat nie odbuduje elementów DOM dla elementów, które już wyrenderował , nawet jeśli obiekty JavaScript w kolekcji mają zostały zastąpione nowymi.


jakieś odniesienie, które to potwierdza?
— azerafati

czy istnieje sposób na wymuszenie ponownego renderowania? czy jakieś inne obejście? nigdzie nie znalazłem tego wspomnianego, ale uważam, że to właśnie tworzy dla mnie bałagan i już zmarnowałem dużo czasu.
— NeverGiveUp161

1
albo nie używaj funkcji śledzenia, ani nie zmieniaj unikalnego identyfikatora przy zmianie obiektu. Zauważ, że nie możesz zmienić $ index, zaleca się, aby nie używać $ index zamiast używać identyfikatora unikalnego dla obiektu (np. Id)
— ram1993
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.