Compreendendo a expressão ngRepeat 'track by'

101

Estou tendo dificuldades para entender como funciona a faixa por expressão de ng-repeat no angularjs. A documentação é muito escassa: http://docs.angularjs.org/api/ng/directive/ngRepeat

Você pode explicar qual é a diferença entre esses dois trechos de código em termos de ligação de dados e outros aspectos relevantes?

com: track by $index

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

sem (mesma saída)

<!--names is an array-->
<div ng-repeat="(key, value) in names">
   <input ng-model="value[key]">                         
</div>
Jonathan Grupp
fonte
Uma ótima pergunta, com respostas muito boas! Que pena que o OP não aceitou uma resposta - ou acha que a pergunta não foi respondida corretamente?
Mawg diz para restabelecer Monica em
Você está certo! Acabei de aceitar a resposta de TJ.
Jonathan Grupp

Respostas:

96

Você pode, track by $indexse sua fonte de dados tiver identificadores duplicados

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

Você não pode iterar esta coleção enquanto usa 'id' como identificador (id duplicado: 1).

NÃO VAI FUNCIONAR:

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

mas você pode, se usar track by $index:

<element ng-repeat="item in dataSource track by $index">
  // something with item ...
</element>
nilsK
fonte
1
obrigado pela sua resposta! Mas certamente os identificadores duplicados não são o único caso de uso. Também gostaria de saber o que está acontecendo "por baixo do capô".
Jonathan Grupp
2
bem, isso é fácil: basta dar uma olhada no código , é tudo open source;)
nilsK
4
Esta questão é antiga, mas ainda acho que pode ajudar a entender muito melhor bennadel.com/blog/… versão curta da explicação aqui docs.angularjs.org/error/ngRepeat/dupes
Annapoorni D
3
Mais uma coisa a levar em consideração é que, se você puder usar faixa por tecla, obterá melhor desempenho (blog.500tech.com/is-reactjs-fast). Este recurso permite que você associe um objeto JavaScript a um nó ngRepeat DOM (Document Object Model) usando um identificador exclusivo. Com essa associação em vigor, o AngularJS não $ destruirá e recriará nós DOM desnecessariamente. Isso pode ter um enorme benefício de desempenho e experiência do usuário ( bennadel.com/blog/… ).
Braulio
Eu tenho uma lista de 700 itens estranhos. O tempo de renderização foi de 4 segundos a 100 ms. Track by deve ser usado para todos os ngRepeat com base em dados provenientes do resto.
Patrick
60

um breve resumo:

track by é usado para vincular seus dados à geração de DOM (e principalmente à re-geração) feita por ng-repeat.

quando você adiciona, track bybasicamente diz ao angular para gerar um único elemento DOM por objeto de dados na coleção fornecida

isso pode ser útil ao paginar e filtrar, ou em qualquer caso em que objetos são adicionados ou removidos da ng-repeatlista.

normalmente, sem track byangular irá vincular os objetos DOM com a coleção, injetando uma propriedade expando - $$hashKey- em seus objetos JavaScript, e irá regenerá-los (e reassociar um objeto DOM) a cada alteração.

explicação completa:

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

um guia mais prático:

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

(track by está disponível em angular> 1.2)

Nuriel
fonte
8

Se você estiver trabalhando com objetos rastreados pelo identificador (por exemplo, $ index) em vez de todo o objeto e recarregar seus dados mais tarde, o ngRepeat não reconstruirá os elementos DOM para os itens já renderizados , mesmo se os objetos JavaScript na coleção tiverem foi substituído por novos.

ram1993
fonte
alguma referência que comprove isso?
azerafati
existe uma maneira de forçar a re-renderização? ou qualquer outra solução? Não encontrei isso mencionado em nenhum lugar, mas acredito que é isso que está criando uma bagunça para mim e já perdi muito tempo.
NeverGiveUp161
1
não use rastrear ou altere o identificador exclusivo ao alterar o objeto. Observe que você não pode alterar o $ index, é recomendado não usar $ index em vez de usar o identificador exclusivo do objeto (por exemplo, id)
ram1993