在 Angular 4 中使用 trackBy 对 *ngFor 数组进行排序

Mar*_*rgh 3 sorting angularjs-track-by ngfor angular

我在排序和具有 trackBy 函数的数组时遇到问题。用例如下:

我有一个项目数组。所有这些项目都有一个 z-index 属性。我还有一个图层管理器​​,可以编辑每个项目的 z-index。当我想保存我的项目时,我想根据每个项目的 z-index 属性对我的数组进行排序。我的 ngFor 上还有一个 trackBy,用于限制 *ngFor 上的更改检测量。

使用 *ngFor 上的 trackBy 函数,当我对数组进行排序时,项目会切换位置(这很糟糕)。如果我删除 trackBy 函数,则不会发生这种情况,并且项目将根据 z-index 进行排序。

*ngFor:

<div class="item" *ngFor="let item of items; let i = index;trackBy:getUniqueIdentifier">
Run Code Online (Sandbox Code Playgroud)

trackBy 函数:

getUniqueIdentifier(index, item) {
    return this.items.length + ', ' + this.languages._previewLanguage;
}
Run Code Online (Sandbox Code Playgroud)

如您所见,当项目的长度发生变化或我切换语言设置时,*ngFor 会发生变化。我试过添加,+ ', ' + item.zIndex但这不起作用。

排序功能:

sortItemsArrayByZIndex() {
    this.items.sort((i1, i2) => {
        return (i1.zIndex - i2.zIndex);
    });
}
Run Code Online (Sandbox Code Playgroud)

所以看起来 trackBy 和这个 sort 函数由于某种原因存在冲突。现在的结果是,当我使用 sort 函数时,items 数组会根据 z-index 进行排序,但 item 也会切换位置,这意味着它们的维度属性由于某种原因而切换。

我想要的是项目数组根据 z-index 排序,但项目保持它们的尺寸。

我需要如何更改我的 trackBy 函数或排序函数,以便获得我想要的结果?

小智 6

如果您不介意,我会添加我自己的答案来解释为什么您的代码不起作用,因为您只提供了一个没有解释的工作代码。

trackBy 函数

trackBy 函数用于提高性能,并避免不必要的更改检测。您可以提供一个自定义函数,就像您所做的那样,它将创建一个值,该值将被检查以查看是否需要触发更改检测。

问题

你的 trackBy 函数是这样的:

getUniqueIdentifier(index, item) {
  return this.items.length + ', ' + this.languages._previewLanguage;
}
Run Code Online (Sandbox Code Playgroud)

这将返回此类型的值:

90, en-US
Run Code Online (Sandbox Code Playgroud)

除非您从数组中推送/撤回项目,否则where90不会改变,并且 where可以应用于数组的多个项目。这意味着如果您更改索引或其他字段,则不会发生更改检测。en-US

解决方案

由于要对数组进行排序,因此至少必须将索引添加到自定义函数的返回值中。这意味着如果项目的索引发生变化(并且由于您对数组进行排序,它会发生变化),将发生变化检测。

最小代码是:

getUniqueIdentifier(index, item) {
  return index + ', ' + this.languages._previewLanguage + ', ' + this.items.length;
}
Run Code Online (Sandbox Code Playgroud)