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>

¡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>

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)


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.


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
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.