Angular-如何不重建使用* ng创建的列表任何时候触发列表中每个元素的事件

时间:2018-12-29 11:05:10

标签: angular angular-changedetection

我有一个使用<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 ,但这似乎无法解决我的问题。

1 个答案:

答案 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()方法,并将其替换为变量。正如我提到的,每次更改检测运行时都会对其进行评估。我写了一篇文章,介绍了一些可以加快应用程序性能的技巧。

https://medium.com/12-developer-labors/some-things-i-wish-i-knew-before-i-start-to-work-with-angular-part-2-performance-47cd834dc409