Entendiendo la expresión 'rastrear por' ngRepeat

101

Tengo dificultades para comprender cómo funciona la pista por expresión de ng-repeat en angularjs. La documentación es muy escasa: http://docs.angularjs.org/api/ng/directive/ngRepeat

¿Puede explicar cuál es la diferencia entre esos dos fragmentos de código en términos de enlace de datos y otros aspectos relevantes?

con: track by $index

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

sin (misma salida)

<!--names is an array-->
<div ng-repeat="(key, value) in names">
   <input ng-model="value[key]">                         
</div>
Jonathan Grupp
fuente
¡Una gran pregunta, con muy buenas respuestas! Qué lástima que el OP no aceptó una respuesta, ¿o no cree que la pregunta fue respondida correctamente?
Mawg dice reinstalar a Monica
¡Tienes razón! Acabo de aceptar la respuesta de TJ.
Jonathan Grupp

Respuestas:

96

Puede hacerlo track by $indexsi su fuente de datos tiene identificadores duplicados

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

No puede iterar esta colección mientras usa 'id' como identificador (id duplicado: 1).

NO FUNCIONA:

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

pero puede, si usa track by $index:

<element ng-repeat="item in dataSource track by $index">
  // something with item ...
</element>
nilsK
fuente
1
¡gracias por tu respuesta! Pero seguramente los identificadores duplicados no son el único caso de uso. También me gustaría saber qué está pasando "bajo el capó".
Jonathan Grupp
2
bueno, eso es fácil: solo eche un vistazo al código , todo es de código abierto;)
nilsK
4
Esta pregunta es antigua, pero todavía creo que esto podría ayudar a entender mucho mejor bennadel.com/blog/ ... versión corta de la explicación aquí docs.angularjs.org/error/ngRepeat/dupes
Annapoorni D
3
Una cosa más a tener en cuenta es que si puede utilizar pista por clave, obtendrá un mejor rendimiento (blog.500tech.com/is-reactjs-fast). Esta función le permite asociar un objeto JavaScript con un nodo ngRepeat DOM (Modelo de objeto de documento) mediante un identificador único. Con esta asociación en su lugar, AngularJS no $ destruirá y volverá a crear nodos DOM innecesariamente. Esto puede tener un gran beneficio en el rendimiento y la experiencia del usuario ( bennadel.com/blog/… ).
Braulio
Tengo una lista de 700 artículos extraños. El tiempo de renderizado pasó de 4 segundos a 100 ms. Track by debe usarse para todos los ngRepeat basados ​​en datos obtenidos del resto.
Patrick
60

un breve resumen:

track by se utiliza para vincular sus datos con la generación DOM (y principalmente la regeneración) realizada por ng-repeat.

cuando agrega track by, básicamente le dice a angular que genere un solo elemento DOM por objeto de datos en la colección dada

esto podría ser útil al paginar y filtrar, o en cualquier caso en el que se agreguen o eliminen objetos de la ng-repeatlista.

por lo general, sin track byangular vinculará los objetos DOM con la colección inyectando una propiedad expando - $$hashKey- en sus objetos JavaScript, y lo regenerará (y volverá a asociar un objeto DOM) con cada cambio.

explicación completa:

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

una guía más práctica:

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

(Track by está disponible en angular> 1.2)

Nuriel
fuente
8

Si está trabajando con objetos rastreados por el identificador (por ejemplo, $ index) en lugar de todo el objeto y vuelve a cargar sus datos más tarde, ngRepeat no reconstruirá los elementos DOM para los elementos que ya ha renderizado , incluso si los objetos JavaScript de la colección tienen sustituido por otros nuevos.

ram1993
fuente
alguna referencia que demuestre esto?
azerafati
¿Hay alguna forma de forzar la re-renderización? o cualquier otra solución? No he encontrado esto mencionado en ninguna parte, pero creo que esto es lo que me está creando un lío y ya he perdido mucho tiempo.
NeverGiveUp161
1
no utilice track by ni cambie el identificador único al cambiar de objeto. Tenga en cuenta que no puede cambiar $ índice, su recomendable que no utilice $ índice en lugar de utilizar el identificador único de objeto (por ejemplo, id)
ram1993