gpt4 book ai didi

Angular trackBy 返回 *ngFor 中的索引 vs item id

转载 作者:太空狗 更新时间:2023-10-29 17:32:17 25 4
gpt4 key购买 nike

我有一个巨大的 ngFor,经常随着异步数据变化。 TrackBy允许只刷新变化的部分,加进去的时候才真正感受到区别。例如,让 trackBy 返回唯一 ID 对我来说似乎很清楚有什么好处。但我有时会看到样本返回当前索引。

public trackByFn(index, item) { return index }

在我的表中,如果我直接返回 'index' 或 'item.id',我没有注意到任何差异。两者似乎都优化了渲染(但我可能没有发现一些错误的边界情况)。

那么,有人能解释一下当我返回索引时到底发生了什么吗?

最佳答案

根据您的评论和我自己的好奇心,我深入研究了 Angular differ code .我可以为您分解在 3 种不同情况下发生的情况,我想拥有知识也是一件好事:

第一种情况:

No trackBy defined: <div *ngFor="let obj of arrayOfObj">{{obj.key}}</div>

如果没有trackBy已定义, Angular 遍历数组,创建 DOM 元素并在 [ngForOf] 中绑定(bind)模板中的数据. (以上代码可以写成):

<ng-template ngFor let-obj [ngForOf]="arrayOfObj">
<div>{{obj.key}}</div>
</ng-template>

所以基本上,它会创建所有这些 div 元素。最初这对于所有 3 种可能性都是相同的。现在新数据从 API 到达,或多或少是相同的数据,但对数组对象的引用发生了变化,并且来自初始数组中对象的所有引用都不同。如果你没有定义 trackBy 函数,angular 会按身份进行比较 === .这适用于字符串、数字和其他原语(不是那么多)。但是对于对象,这不会。那么如果它开始检查是否有变化,现在会发生什么。它无法再找到原始对象,因此它会删除 DOM 元素(实际上将其存储在某处以供以后使用,如果对象决定返回),并从头开始构建所有模板。

Even if the data hasn't changed, the second response produces objects with different identities, and Angular must tear down the entire DOM and rebuild it (as if all old elements were deleted and all new elements inserted).

您可以想象这会非常耗费 CPU 和内存。

第二种情况:

trackBy defined with object key:

<div *ngFor="let obj of arrayOfObj;trackBy:trackByKey">{{obj.key}}</div>

trackByKey = (index: number, obj: object): string => {
return object.key;
};

让我们先做这个。这是最快的。所以我们正处于新数据进来的时刻,具有与以前不同身份的对象。此时,angular 在这个 trackBy 函数上迭代所有新对象并获得对象的标识。它会将它交叉引用到现有的(如果没有找到则之前删除的)DOM 元素。如果找到,它仍将更新在模板内进行的任何绑定(bind)。如果没有找到,它将检查之前删除的对象,如果仍然找不到,它将从模板创建一个新的 DOM 元素并更新绑定(bind)。所以,这很快。只是寻找已经创建的 DOM 元素,并更新绑定(bind),angular 可以快速快速地完成。

第三种情况:

trackBy defined with array index

<div *ngFor="let obj of arrayOfObj;trackBy:trackByIndex">{{obj.key}}</div>

trackByIndex = (index: number): number => {
return index;
};

这与 trackBy 对象键的故事相同,但有一点不同,即如果你去玩弄数组中的元素,模板中的绑定(bind)会不断更新。但这仍然很快,但很可能不是最快的方法 :),尽管它比重新创建整个 DOM 快得多。

希望您现在有所不同。不过还有一些额外的东西。如果你有很多业务对象,它们都有相同的方式来访问它们的身份,比如属性 .id.key ,您可以扩展 native *ngFor并创建你自己的结构指令,它有这个 trackBy内置函数。虽然未经测试的代码:

export interface BaseBo {
key: string;
}

@Directive({selector: '[boFor][boForOf]'})
export class ForOfDirective<T extends BaseBo> extends NgForOf<T> {
@Input()
set boForOf(boForOf: T[]) {
this.ngForOf = boForOf;
}

ngForTrackBy = (index: number, obj: T) => obj.key;
}

关于Angular trackBy 返回 *ngFor 中的索引 vs item id,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54478273/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com