Angular - ngFor 和 trackBy 与异步管道

标签 angular performance rxjs ngfor

我想用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 }))));
  }
}

模板
<div *ngFor="let d of data | async; trackBy: trackBy">{{d}}</div>

另外这里还有一个 StackBlitz . div每次将新值发送到 ngFor 时都会重新渲染标签.

据我了解 trackBy它应该检测对象是否相同(通过 id 属性),尽管引用已更改。还是我显然错过了什么?

最佳答案

你说得对,trackBy可用于避免在对象未更改时重新渲染组件。一边做 ngFor在字符串或数字上,这对 Angular 很明显,但在复杂对象上则不然。

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

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

这个 Observable 的结果:
 []
 [{id: 0}]
 [{id: 0}, {id: 1}]
 ...

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

使用此 trackBy 功能时,每次列表更改时所有组件都会呈现:
trackBy(index, item) {
    return Math.random();
}

使用此 trackBy 函数时,每个组件仅渲染一次:
trackBy(index, item) {
    return item.id;
}

Here you can find the running example.

关于Angular - ngFor 和 trackBy 与异步管道,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57918301/

相关文章:

c++ - 使用 Boost Karma 替换 std::stringstream 进行 double 到 std::string 的转换

performance - 如何加快行进立方体?

html - 为笔画 dashoffset 设置动画时使用过多 CPU 资源使用 SVG 路径创建的边框

html - Angular - 基于用户输入的构建表单

javascript - 使用 RxJS 同时点击鼠标左右键

angular - 使用 asyncPipe 渲染数据

javascript - 组合观测值并按日期排序

javascript - 从外部将值传递给 Angular 应用程序

javascript - 如何将自定义 HTML 添加到 ngx Typeahead?

unit-testing - 如何对 Angular2 中调用 window.location.href 的函数进行单元测试