【问题标题】:Angular - How to not rebuild a list created with *ngFor any time an event on each element of the list is firedAngular - 如何在任何时候触发列表的每个元素上的事件时不重建使用 *ngFor 创建的列表
【发布时间】:2018-12-29 11:05:10
【问题描述】:

我有一个使用*ngFor 指令生成的<div> 的简单列表,类似于

<div *ngFor="let item of items() | async ; let i=index" 
  [ngClass]="getItemClass(i)"
  (click)="itemClick(i)"</div>

如您所见,只要方法 items() 返回的 Observable 发出,列表就会异步填充。在我的情况下,这样的 Observable 是ReplaySubject,如果知道这有什么用的话。然后,我使用方法getItemClass 定义要应用于每个&lt;div&gt; 元素的类。

我还想使用itemClick(i: number) 方法对每个项目上的点击事件做出反应。

问题

任何时候单击div 元素,即任何时候运行itemClick(i: number) 方法,似乎&lt;div&gt;s 的整个列表都会重新构建。我得出这个结论,观察到任何时候单击 div 元素时,items() 方法也会运行。

问题

是否可以在单击&lt;div&gt; 元素之一时避免重建列表?我已经将changeDetection 设置为 OnPush,但它似乎没有解决我的问题。

【问题讨论】:

标签: angular angular-changedetection


【解决方案1】:

是的,即使使用 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

【讨论】:

  • 谢谢,这很有意义。你知道使用 NgZone 是否可以得到相同的结果吗?
  • 有但不值得。它基本上归结为以角度禁用 NgZone,然后手动触发更改检测。这很难,因为要考虑很多极端情况。关于这个主题的非常酷的文章:blog.angularindepth.com/…
猜你喜欢
  • 1970-01-01
  • 2010-10-18
  • 2022-01-26
  • 2023-03-30
  • 2012-06-05
  • 2020-11-14
  • 2020-07-19
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多