在 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:
<div class="item" *ngFor="let item of items; let i = index;trackBy:getUniqueIdentifier">
trackBy函数:
getUniqueIdentifier(index, item) {
return this.items.length + ', ' + this.languages._previewLanguage;
}
如您所见,当项目的长度发生变化或者我切换语言设置时,*ngFor 也会发生变化。我试过添加 + ', ' + item.zIndex
但这不起作用。
排序函数:
sortItemsArrayByZIndex() {
this.items.sort((i1, i2) => {
return (i1.zIndex - i2.zIndex);
});
}
看来trackBy和这个sort函数不知为何有些冲突。现在的结果是,当我使用排序函数时,项目数组根据 z-index 排序,但项目也会切换位置,这意味着它们的尺寸属性由于某种原因被切换。
我想要的是项目数组根据 z-index 排序,但项目保持其尺寸。
我需要如何更改我的 trackBy 函数或我的排序函数才能得到我想要的结果?
正如用户@trichetriche 提到的,我需要将索引和 zIndex 属性 添加到 trackBy,让 TrackBy 按预期工作。
trackBy 函数看起来像这样:
getUniqueIdentifier(index, item) {
return index + ', ' + item.zIndex + ', ' + this.languages._previewLanguage + ', ' + this.items.length;
}
如果您不介意,我会添加我自己的答案来解释为什么您的代码无法正常工作,因为您只提供了一个工作代码而没有任何解释。
trackBy 函数
trackBy 函数是为了提高性能,避免不必要的变化检测。您可以提供一个自定义函数,就像您所做的那样,它将创建一个值,该值将被检查以查看是否需要触发更改检测。
问题
您的 trackBy 函数是这样的:
getUniqueIdentifier(index, item) {
return this.items.length + ', ' + this.languages._previewLanguage;
}
这将 return 这种类型的值:
90, en-US
90
不会改变 除非你 push/withdraw 数组中的项目,而 en-US
可以应用于数组的几个项目。这意味着如果您更改索引或其他字段,则不会发生更改检测。
解决方案
既然你想对你的数组进行排序,你必须至少将 索引 添加到自定义函数的 return 中。这意味着如果项目的索引发生变化(并且由于您对数组进行排序,它会发生变化),就会发生变化检测。
最小代码为:
getUniqueIdentifier(index, item) {
return index + ', ' + this.languages._previewLanguage + ', ' + this.items.length;
}
我在排序和具有 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">
trackBy函数:
getUniqueIdentifier(index, item) {
return this.items.length + ', ' + this.languages._previewLanguage;
}
如您所见,当项目的长度发生变化或者我切换语言设置时,*ngFor 也会发生变化。我试过添加 + ', ' + item.zIndex
但这不起作用。
排序函数:
sortItemsArrayByZIndex() {
this.items.sort((i1, i2) => {
return (i1.zIndex - i2.zIndex);
});
}
看来trackBy和这个sort函数不知为何有些冲突。现在的结果是,当我使用排序函数时,项目数组根据 z-index 排序,但项目也会切换位置,这意味着它们的尺寸属性由于某种原因被切换。
我想要的是项目数组根据 z-index 排序,但项目保持其尺寸。
我需要如何更改我的 trackBy 函数或我的排序函数才能得到我想要的结果?
正如用户@trichetriche 提到的,我需要将索引和 zIndex 属性 添加到 trackBy,让 TrackBy 按预期工作。
trackBy 函数看起来像这样:
getUniqueIdentifier(index, item) {
return index + ', ' + item.zIndex + ', ' + this.languages._previewLanguage + ', ' + this.items.length;
}
如果您不介意,我会添加我自己的答案来解释为什么您的代码无法正常工作,因为您只提供了一个工作代码而没有任何解释。
trackBy 函数
trackBy 函数是为了提高性能,避免不必要的变化检测。您可以提供一个自定义函数,就像您所做的那样,它将创建一个值,该值将被检查以查看是否需要触发更改检测。
问题
您的 trackBy 函数是这样的:
getUniqueIdentifier(index, item) {
return this.items.length + ', ' + this.languages._previewLanguage;
}
这将 return 这种类型的值:
90, en-US
90
不会改变 除非你 push/withdraw 数组中的项目,而 en-US
可以应用于数组的几个项目。这意味着如果您更改索引或其他字段,则不会发生更改检测。
解决方案
既然你想对你的数组进行排序,你必须至少将 索引 添加到自定义函数的 return 中。这意味着如果项目的索引发生变化(并且由于您对数组进行排序,它会发生变化),就会发生变化检测。
最小代码为:
getUniqueIdentifier(index, item) {
return index + ', ' + this.languages._previewLanguage + ', ' + this.items.length;
}