Html 将trackBy与ngFor有效结合使用

Html 将trackBy与ngFor有效结合使用,html,angular,performance,ngfor,Html,Angular,Performance,Ngfor,在Angular中,*ngFor是否需要trackBy函数?我看了几篇文章,其中说使用trackBy将提高性能并具有更好的内存管理。但我想知道trackBy是否是一种改进,那么为什么它不是默认行为呢?这是默认行为,我看到的一切都过时了吗 如果它不是默认行为,我的项目在90个组件中有大约90*ngFor,我想知道是否有一种方法可以使用trackBy,在这里我不包括以下函数90次。我还想避免添加一个服务并导入90次 HTML <mat-option *ngFor="let l of list;

在Angular中,*ngFor是否需要trackBy函数?我看了几篇文章,其中说使用trackBy将提高性能并具有更好的内存管理。但我想知道trackBy是否是一种改进,那么为什么它不是默认行为呢?这是默认行为,我看到的一切都过时了吗

如果它不是默认行为,我的项目在90个组件中有大约90*ngFor,我想知道是否有一种方法可以使用trackBy,在这里我不包括以下函数90次。我还想避免添加一个服务并导入90次

HTML

<mat-option *ngFor="let l of list; trackBy: trackByFn" [value]="l.id">
   {{l.name}}
</mat-option>

请注意,您的示例中没有一个使用索引(除了一篇不可靠的媒体文章),它们都使用对象的唯一标识符,除非您告诉它,否则angular不可能知道该标识符

单独返回索引有一个用例,但这是一个相当少见的用例。它基本上告诉angular永远不要重新命名列表中的现有项,因为给定项的索引永远不会更改。对于开发人员来说,这通常是一个非常意外的行为,因为子组件的初始化生命周期挂钩不会重新执行。在没有子组件的ngFor中,这样做通常是安全的,但无论如何,这些类型的列表通常性能更好,除非列表很长或经常更改,否则您不会看到太多好处


trackBy的思想是允许您重新初始化列表中需要它的项,而不是重新初始化不需要它的项。它不是像某些人对待它那样盲目提高性能的灵丹妙药,它的用途和功能应该得到充分理解。请记住,仅仅因为项目具有唯一的ID并不意味着它适合在trackBy函数中使用。trackBy的意思是告诉angular何时需要重新渲染一个项目,即何时需要重新运行那些生命周期挂钩。如果ID保持不变,但内容可能会发生变化,这取决于您构建某个组件的方式,那么该组件可能仍需要重新初始化。

给它一个类进行测试

export class Item {
  id: number;
  name: string;
}
并添加一个指令来监视其init和destory

@Directive({selector: '[appMonitor]'})
export class MonitorDirective implements OnInit, OnDestroy {


  ngOnInit(): void {
    console.log('init');
  }

  ngOnDestroy(): void {
    console.log('destroy');
  }
}
在阵列中

  itemArray: Item[] = [
    {id: 1, name: 'Tom'},
    {id: 2, name: 'Joe'},
    {id: 3, name: 'KK'}
  ];
用于更改数组内容的两个函数

  allFoo(): void {
    this.itemArray = [
      {id: 1, name: 'Tom_foo'},
      {id: 2, name: 'Joe_foo'},
      {id: 3, name: 'KK_foo'}
    ];
  }

  allBar(): void {
    this.itemArray = [
      {id: 1, name: 'Tom_bar'},
      {id: 2, name: 'Joe_bar'},
      {id: 3, name: 'KK_bar'}
    ];
  }
准备工作已经完成,到目前为止还不错。 首先,让我们在没有trackBy的情况下进行测试

  <div *ngFor="let item of itemArray " appMonitor>
    Id: {{item.id}} Name:{{item.name}}
  </div>


组件正在恢复。因此,我们可以得出结论,使用trackBy可以节省在hmtl中创建相同组件的工作。

好,那么让我们假设我使用
return item.id
。因为它是一个唯一的标识符,所以我应该看到一些内存/性能的提高?如果是这样,有没有更干净的方法来使用trackBy而不在每个组件中创建函数?item.id肯定会提高性能,因为angular知道何时会这样做,并且不需要在ngFor中重新渲染项目,但是如果项目没有id属性,则显然会中断。据我所知,没有全局方法设置trackBy,这也没有多大意义,因为在某些情况下需要重写它。你能得到的最接近的是某种基本的“ListComponent”,它实现了你自己设计的默认trackByFn,但是你仍然需要在模板中明确声明它的用法。我编辑了我的答案,以便在TrackBy的用法中更清楚/更详细谢谢你的回答,假设我的所有对象都有id,因为它们都来自db。我们有一个组件,可以在其中添加公共函数,但我们需要将其添加到导入、提供程序和构造函数中,以便能够在html中引用它,这与
return item.id
函数的行数相同。我只是想看看是否有一种有效的方法来添加它,而不必添加这么多行复制/粘贴的代码。正如我所说,您可以创建一个实现该函数的基列表组件类,并让任何带有ngFor的组件从中继承。这可能与导入和构造的行数相同,但如果需要更改,则更改将非常容易。如果您使用angular cli做得足够好,那么实际上可以对其进行设置,以便它可以为您构建此组件。
  <div *ngFor="let item of itemArray " appMonitor>
    Id: {{item.id}} Name:{{item.name}}
  </div>
<div *ngFor="let item of itemArray ;trackBy:identify" appMonitor>
  Id: {{item.id}} Name:{{item.name}}
</div>
  identify(index: number, item: Item): number {
    return item.id;
  }