在Angular中,* ngFor需要trackBy函数吗?我看到一些文章here,here,here和here表示使用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
}
答案 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>
很明显,每次更改数组 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;
}
组件正在恢复。因此我们可以得出结论,使用 trackBy 可以节省在 hmtl 中创建相同组件的工作。