Penso che una delle cose che uno sviluppatore deve affrontare quando usa ngRepeat
, è quella in cui i
ha lo stesso valore in un array, come in ng-repeat="i in myCtrl.arr"
, quindi:
angular.js:13236 Error: [ngRepeat:dupes] Duplicates in a repeater are not allowed.
Use 'track by' expression to specify unique keys.
Penso che sia dovuto ad AngularJS che memorizza nella cache gli elementi DOM usando i
come chiave hash, e quindi se il valore può duplicare (duplicare un valore precedente), dobbiamo usare
ng-repeat="i in myCtrl.arr track by $index"
o qualunque cosa sia unica durante il loop di ciascun elemento.
La domanda è, quando sarà utile tale memorizzazione nella cache? È solo quando gli oggetti verranno riorganizzati, ad esempio se arr
viene ordinato in un altro modo (in tal caso, il caching di $index
bloccherà automaticamente la cache? Perché il $index
è 1
nel nuovo array è non uguale a $index
che è 1
prima). In che modo AngularJS conosce e interrompe la cache in questo modo ... è track by $index
lo stesso che pronunciare una frase ipotetica do not use cache
o track by no cache
?
Ad esempio, se usiamo
myRecord in myCtrl.myRecords track by myRecord.id
supponendo che myRecord
sia una riga di database che ha il campo chiamato id
ed è univoco, AngularJS può memorizzare nella cache gli elementi DOM e riutilizzare quando gli elementi DOM vengono riorganizzati, sia ordinati in modi diversi che inserendo, eliminando un elemento nella ripetizione? (anche se, penso che ripetere un dizionario non abbia un ordine definito dopo una certa versione di AngularJS, come ad esempio con AngularJS 1.3?)
Diciamo se lo facciamo
<li ng-repeat="rec in myCtrl.authors track by rec.id">{{rec.id}} {{rec.name}}</li>
e nel controller:
vm.authors = [{id: 2, name: "mike"}, {id: 3, name: "jessy"}, {id: 4, name: "mike"}];
$timeout(function() {
vm.authors[0].id = 1;
vm.authors.unshift({id: 2, name: "lucy"});
}, 3000);
Vedo tutti i record aggiornati correttamente dopo 3 secondi. Non vedo il record lucy
utilizzando l'elemento DOM mike
(e quindi mostrando mike
in esso).
E un'altra cosa che ho provato è stata scambiare il id
degli elementi dell'array:
vm.authors[0].id = 3;
vm.authors[1].id = 2;
E tutto viene aggiornato correttamente sullo schermo.
Quindi il caching del DOM memorizza realmente nella cache l'elemento DOM vuoto come una "shell" vuota? In tal caso, AngularJS non può utilizzare solo track by $index
per mantenere un inventario delle shell vuote?