Понимание выражения ngRepeat 'track by'

102

Мне сложно понять, как работает трек по выражению ng-repeat в angularjs. Документация очень скудная: http://docs.angularjs.org/api/ng/directive/ngRepeat

Можете ли вы объяснить, в чем разница между этими двумя фрагментами кода с точки зрения привязки данных и других важных аспектов?

с участием: track by $index

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

без (такой же выход)

<!--names is an array-->
<div ng-repeat="(key, value) in names">
   <input ng-model="value[key]">                         
</div>
Джонатан Групп
источник
Отличный вопрос с очень хорошими ответами! Как жаль, что ОП не принял ответ - или вы не думаете, что на вопрос ответили правильно?
Mawg требует восстановить Монику
Ты прав! Я только что принял ответ Ти Джея.
Джонатан Групп

Ответы:

97

Вы можете, track by $indexесли ваш источник данных имеет повторяющиеся идентификаторы

например: $scope.dataSource: [{id:1,name:'one'}, {id:1,name:'one too'}, {id:2,name:'two'}]

Вы не можете перебирать эту коллекцию, используя id в качестве идентификатора (повторяющийся идентификатор: 1).

НЕ РАБОТАЕТ:

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

но вы можете, если используете track by $index:

<element ng-repeat="item in dataSource track by $index">
  // something with item ...
</element>
nilsK
источник
1
спасибо за Ваш ответ! Но, конечно же, повторяющиеся идентификаторы - не единственный вариант использования. Также хотелось бы знать, что происходит «под капотом».
Джонатан Групп
2
ну, это просто: просто взгляните на код , он полностью открытый;)
nilsK
4
Это старый вопрос, но я все же думаю, что он может помочь лучше понять bennadel.com/blog/… краткая версия объяснения здесь docs.angularjs.org/error/ngRepeat/dupes
Annapoorni D
3
Еще одна вещь, которую следует принять во внимание, заключается в том, что если вы можете использовать отслеживание по ключу, вы получите лучшую производительность (blog.500tech.com/is-reactjs-fast). Эта функция позволяет связать объект JavaScript с узлом ngRepeat DOM (Document Object Model), используя уникальный идентификатор. При наличии этой связи AngularJS не будет уничтожать и повторно создавать узлы DOM без необходимости. Это может иметь огромное преимущество в производительности и удобстве использования ( bennadel.com/blog/… ).
Braulio
У меня есть список из 700 с лишним пунктов. Время рендеринга увеличилось с 4 секунд до 100 мс. Track by следует использовать для всех ngRepeat на основе данных, полученных из rest.
Патрик
60

краткое содержание:

track by используется для связывания ваших данных с генерацией DOM (и в основном повторной генерацией), созданной ng-repeat.

когда вы добавляете, track byвы в основном указываете angular генерировать один элемент DOM для каждого объекта данных в данной коллекции

это может быть полезно при разбиении по страницам и фильтрации, или в любом случае, когда объекты добавляются или удаляются из ng-repeatсписка.

Обычно без track byangular объекты DOM связываются с коллекцией, внедряя свойство expando - $$hashKey- в ваши объекты JavaScript и регенерируя его (и повторно связывая объект DOM) с каждым изменением.

полное объяснение:

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

более практическое руководство:

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

(track by доступен в angular> 1.2)

Нуриэль
источник
8

Если вы работаете с объектами, отслеживаемыми по идентификатору (например, $ index), а не по всему объекту, и вы перезагружаете свои данные позже, ngRepeat не будет перестраивать элементы DOM для элементов, которые он уже визуализировал , даже если объекты JavaScript в коллекции имеют были заменены на новые.

таран1993
источник
любая ссылка, подтверждающая это?
azerafati
есть ли способ принудительного повторного рендеринга? или любая другая работа? Я нигде не нашел об этом упоминания, но я считаю, что это то, что создавало для меня беспорядок, и я уже потратил много времени.
NeverGiveUp161
1
либо не использовать track by, либо менять уникальный идентификатор при изменении объекта. Обратите внимание, что вы не можете изменить $ index, рекомендуется не использовать $ index вместо использования идентификатора, уникального для объекта (например, id)
ram1993