web-dev-qa-db-fra.com

Comment utiliser trackBy avec ngFor

Je ne peux pas vraiment comprendre ce que je devrais retourner de trackBy. D'après des exemples que j'ai vus sur le Web, je devrais renvoyer la valeur d'une propriété sur l'objet. Est-ce correct? Pourquoi ai-je l'index en paramètre?

Par exemple, dans le cas suivant:

constructor() {
    window.setInterval(() => this.users = [
            {name: 'user1', score: Math.random()},
            {name: 'user2', score: Math.random()}],
        1000);
}

userByName(index, user) {
    return user.name;
}

...

<div *ngFor="let user of users; trackBy:userByName">{{user.name}} -> {{user.score}}</div>

Les objets affichés dans le modèle sont toujours mis à jour malgré le nom inchangé. Pourquoi?

27

À chaque ngDoCheck déclenchée pour la directive ngForOf Angular vérifie quels objets ont changé. Il utilise diffère pour ce processus et utilise différemment trackBy function pour comparer l'objet actuel au nouvel objet.La fonction par défaut trackBy suit les éléments par identité:

const trackByIdentity = (index: number, item: any) => item;

Il reçoit l'élément en cours et devrait renvoyer une valeur. Ensuite, la valeur renvoyée par la fonction est comparée à la valeur que cette fonction a renvoyée la dernière fois. Si la valeur change, la différence signale une modification. Ainsi, si la fonction par défaut retourne des références d'objet, elle ne correspondra pas à l'élément actuel si la référence d'objet a changé. Vous pouvez donc fournir votre fonction personnalisée trackBy qui renverra quelque chose d’autre. Par exemple, une valeur clé de l'objet. Si cette valeur de clé correspond à la précédente, alors Angular ne détectera pas le changement.

La syntaxe ...trackBy:userByName n'est plus pris en charge. Vous devez maintenant fournir une référence de fonction. Voici l'exemple de base:

setInterval( () => {
  this.list.length = 0;
  this.list.Push({name: 'Gustavo'});
  this.list.Push({name: 'Costa'});
}, 2000);

@Component({
  selector: 'my-app',
  template: `
   <li *ngFor="let item of list; trackBy:identify">{{item.name}}</li>
  `
})
export class App {
  list:[];

  identify(index, item){
     return item.name; 
  }

Bien que la référence à l'objet change, le DOM n'est pas mis à jour. voici le plongeur. Si vous êtes curieux de savoir comment ngFor fonctionne sous le capot, lisez cette réponse .

36