1. ホーム
  2. angular

[解決済み] trackBy` と `ngFor` の使い方

2022-08-19 05:50:19

質問

からの戻り値がよくわからないのですが。 trackBy . ウェブで見たいくつかの例に基づいて、私はオブジェクトのいくつかのプロパティの値を返すべきだと思います。これは正しいのでしょうか?なぜ私は index をパラメータとして取得する必要があるのでしょうか?

例えば、以下のような場合です。

コンポーネント.component.ts

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

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

コンポーネント.テンプレート.html

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

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

どのように解決するのですか?

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

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

これは現在の項目を受け取り、何らかの値を返す必要があります。そして、この関数によって返された値は、この関数が前回返した値と比較されます。もし値が変われば、differentは変更を報告します。そのため、デフォルトの関数がオブジェクト参照を返す場合、オブジェクト参照が変更されると現在の項目と一致しなくなります。そこで、カスタムの 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 がボンネットの下でどのように動作するのか気になる方は この回答を読む .