我想使用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属性)检测到对象相同。还是我明显缺少什么?
答案 0 :(得分:0)
是的,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(index, item) {
return Math.random();
}
使用此trackBy函数时,每个组件仅呈现一次:
trackBy(index, item) {
return item.id;
}