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

sorting an *ngFor array with trackBy in Angular 4

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

我有一个项目数组。所有这些项目都具有z-index属性。我还有一个图层管理器??,可以编辑每个项目的z-index。当我要保存项目时,我想根据每个项目的z-index属性对数组进行排序。我的ngFor上也有一个trackBy来限制* ngFor。

上的更改检测量。

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

* ngFor:

1
 

trackBy函数:

1
2
3
getUniqueIdentifier(index, item) {
    return this.items.length + ', ' + this.languages._previewLanguage;
}

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

排序功能:

1
2
3
4
5
sortItemsArrayByZIndex() {
    this.items.sort((i1, i2) => {
        return (i1.zIndex - i2.zIndex);
    });
}

因此,出于某种原因,trackBy和此排序函数似乎发生了冲突。现在的结果是,当我使用sort函数时,items数组将根据z-index进行排序,但是item也会切换位置,这意味着它们的尺寸属性由于某种原因而被切换。

我想要的是items数组是根据z-index排序的,但是这些item保持其尺寸。

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


如果您不介意,我将添加我自己的答案以解释您的代码为何不起作用,因为您只提供了有效的代码而没有任何解释。

trackBy功能

使用trackBy函数可以提高性能,并避免不必要的更改检测。您可以像以前一样提供自定义函数,它将创建一个值,将对其进行检查以查看是否需要触发更改检测。

问题

您的trackBy函数是这样的:

1
2
3
getUniqueIdentifier(index, item) {
  return this.items.length + ', ' + this.languages._previewLanguage;
}

这将返回以下类型的值:

1
90, en-US

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

解决方案

由于要对数组进行排序,因此必须至少将索引添加到自定义函数的返回中。这意味着,如果项的索引发生更改(并且由于对数组进行了排序,则将对其进行更改),则将进行更改检测。

最小代码为:

1
2
3
getUniqueIdentifier(index, item) {
  return index + ', ' + this.languages._previewLanguage + ', ' + this.items.length;
}


作为用户@trichetriche提到,我需要添加索引以及trackBy的zIndex属性,以使TrackBy可以按预期工作。

trackBy函数如下所示:

1
2
3
getUniqueIdentifier(index, item) {
    return index + ', ' + item.zIndex + ', ' + this.languages._previewLanguage + ', ' + this.items.length;
}