Angular - 带有异步管道的 ngFor 和 trackBy

kno*_*fel 5 performance rxjs ngfor angular

我想用它trackBy来提高一长串的性能。该列表的数据在更改时应该是不可变的,并通过异步管道提供给模板。尽管我正在使用该trackBy功能,但每次发出新值时都会重新呈现整个列表。即使数组内的对象保持相同且相同,也会发生这种情况id

成分

export class AppComponent implements OnInit {
  data: Observable<any>;

  trackBy(index, item) {
    return item.id;
  }

  ngOnInit() {
    const data = interval(100).pipe(mapTo([
      { id: 1 }, { id: 2 }
    ]))

    this.data = data.pipe(map(events => events.map(event => ({ ...event }))));
  }
}
Run Code Online (Sandbox Code Playgroud)

模板

<div *ngFor="let d of data | async; trackBy: trackBy">{{d}}</div>
Run Code Online (Sandbox Code Playgroud)

另外这里还有一个StackBlitzdiv每次将新值发送到 时,标签都会重新呈现ngFor

据我了解,trackBy尽管引用发生了变化,但它应该检测到对象是相同的(通过 id 属性)。或者我明显错过了什么?

ibe*_*oun 2

你是对的,trackBy当对象没有改变时,可以用来避免重新渲染组件。在字符串或数字上执行操作时ngFor,这对于 Angular 来说是显而易见的,但在复杂对象上则不然。

我做了一个小例子来解释不同的情况,从这个 Observable 开始:

this.animals = interval(1000)
    .pipe(take(30),
    map(v => ({ id: v} as Animal)),
    scan((acc, curr) => [...acc, curr], []));
Run Code Online (Sandbox Code Playgroud)

这个 Observable 的结果:

 []
 [{id: 0}]
 [{id: 0}, {id: 1}]
 ...
Run Code Online (Sandbox Code Playgroud)

我创建了一个显示输入并在每次渲染时具有随机颜色的组件,以使渲染更加明显。

使用此 trackBy 函数时,每次列表更改时都会呈现所有组件:

trackBy(index, item) {
    return Math.random();
}
Run Code Online (Sandbox Code Playgroud)

使用此 trackBy 函数时,每个组件仅渲染一次:

trackBy(index, item) {
    return item.id;
}
Run Code Online (Sandbox Code Playgroud)

在这里您可以找到正在运行的示例。