web-dev-qa-db-ja.com

ngForでtrackByを使用する方法

trackByから何を返すべきか本当に理解できません。 Webで見た例に基づいて、オブジェクトのプロパティの値を返す必要があります。それが正しいか?なぜパラメーターとしてインデックスを取得するのですか?

たとえば、次の場合:

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>

テンプレートに表示されるオブジェクトは、名前が変更されていないにもかかわらず更新されます。どうして?

ngDoCheckディレクティブに対してトリガーされた各ngForOfで、Angularはどのオブジェクトが変更されたかをチェックします。このプロセスでは使用方法が異なり、それぞれがtrackBy関数を使用して比較します現在のオブジェクトと新しいオブジェクトデフォルトのtrackBy関数は、IDによってアイテムを追跡します。

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

現在のアイテムを受け取り、何らかの値を返す必要があります。次に、関数によって返された値は、この関数が最後に返した値と比較されます。値が変更された場合、差異は変更を報告します。そのため、デフォルト関数がオブジェクト参照を返す場合、オブジェクト参照が変更されていると、現在のアイテムと一致しません。そのため、他の何かを返すカスタムtrackBy関数を提供できます。たとえば、オブジェクトのキー値。このキー値が前のものと一致する場合、Angularは変更を検出しません。

構文...trackBy:userByNameはサポートされなくなりました。ここで、関数参照を提供する必要があります。基本的な例を次に示します。

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; 
  }

オブジェクト参照は変更されますが、DOMは更新されません。 こちら プランカー。 ngForが内部でどのように機能するか興味がある場合は、 この答えを読んでください