我有一个使用<div>
指令生成的*ngFor
的简单列表,类似
<div *ngFor="let item of items() | async ; let i=index"
[ngClass]="getItemClass(i)"
(click)="itemClick(i)"</div>
如您所见,列表每次由方法items()
返回的Observable发出时都是异步填充的。就我而言,这样的Observable是ReplaySubject
(如果可以知道)。然后,我使用方法<div>
定义要应用于每个getItemClass
元素的类。
我还想使用方法itemClick(i: number)
对每个项目的单击事件做出反应。
问题
每次单击div
元素时,即每次运行itemClick(i: number)
方法时,似乎都将重建<div>
的整个列表。我得出这个结论,观察到每次单击div
元素时,也会运行items()
方法。
问题
是否可以避免单击<div>
元素之一时重建列表?我已经将changeDetection
设置为 OnPush ,但这似乎无法解决我的问题。
答案 0 :(得分:2)
是的,即使使用onPush,也会触发更改检测。这将导致对index()方法的评估。这有点丢在文档中。任何会冒泡到zone.js代码的事件,都会触发从根到该组件的每个组件的更改检测。设置onPush不会阻止这种情况。为了避免在循环中重新创建组件,您需要添加trackBy。
在您的html模板中:
<li *ngFor="let hr of heroes;trackBy: trackByFn">{{hr.name}}</li>
,然后在组件中必须定义函数:
trackByFn(index, item) {
return item.id
}
项目从循环中传递。并且如果该项目的ID不变,则不会重新创建该项目。
我也将摆脱index()方法,并将其替换为变量。正如我提到的,每次更改检测运行时都会对其进行评估。我写了一篇文章,介绍了一些可以加快应用程序性能的技巧。