使用trackBy和ngFor高效地角度

时间:2018-04-17 15:05:41

标签: html angular performance ngfor

在Angular中,* ngFor需要trackBy函数吗?我看到一些文章herehereherehere表示使用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>

TS

trackByFn(index, item) {
    return index
}

2 个答案:

答案 0 :(得分:4)

请注意,没有一个示例使用索引(除了一篇不可靠的媒体文章),它们都使用了角度无法知道的对象的唯一标识符,除非您告诉它。

单独返回索引有一个用例,但这是一个相当罕见的用例。由于给定项目的索引永远不会改变,所以它基本上是告诉角度从不重新渲染此列表中的现有项目。这通常是开发人员非常意外的行为,因为子组件的初始化生命周期钩子不会重新执行。这通常是安全的,但在没有子组件的ngFor中,但这些类型的列表通常更高效,除非列表很长或经常更改,否则您将看不到多少好处。

trackBy的想法是允许您重新初始化需要它的列表中的项目,而不是重新初始化那些不需要它的项目。它不是像一些人一样盲目提高性能的灵丹妙药,它的目的和功能应该被充分理解。请记住,仅仅因为项目具有唯一ID并不意味着它适合在trackBy函数中使用。 trackBy用于表示需要重新渲染项目时的角度,即当我需要重新运行这些生命周期钩子时。如果ID保持不变但内容可以更改,则根据您构建某个组件的方式,该组件可能需要重新初始化。

答案 1 :(得分:1)

给它一个测试类

export class Item {
  id: number;
  name: string;
}

并添加一个指令来监控它的初始化和销毁​​

@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>

enter image description here

很明显,每次更改数组 angular 都会相应地重新创建组件。这次让我们尝试 trackBy:

<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;
  }

enter image description here

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