简体   繁体   English

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

[英]sorting an *ngFor array with trackBy in Angular 4

i'm having trouble sorting and array that has a trackBy function. 我在排序和具有trackBy功能的数组时遇到问题。 The use case is as follows: 用例如下:

I have an item array. 我有一个项目数组。 All these items have a z-index property. 所有这些项都具有z-index属性。 I also have a layer manager that can edit the z-index of each item. 我还有一个图层管理器​​,可以编辑每个项目的z-index。 When I want to save my items, I want to sort my array according to the z-index property of each item. 当我想保存我的项目时,我想根据每个项目的z-index属性对我的数组进行排序。 I also have a trackBy on my ngFor to limit the amount of change detection on the *ngFor. 我还有一个跟踪我的ngFor来限制* ngFor的变化检测量。

With a trackBy function on my *ngFor, the items switch places when I sort the array (which is bad). 使用我的* ngFor上的trackBy函数,当我对数组进行排序时(不好),项目切换位置。 If I remove the trackBy function this doesn't happen, and the items are sorted according to z-index. 如果我删除了trackBy函数,则不会发生这种情况,并且根据z-index对项目进行排序。

The *ngFor: * ngFor:

<div class="item" *ngFor="let item of items; let i = index;trackBy:getUniqueIdentifier">

The trackBy function: trackBy功能:

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

As you can see, the *ngFor is changed when the length of the items changes or if I switch my language settings. 如您所见,当项目的长度发生变化或我切换语言设置时,* ngFor会发生变化。 I've tried adding + ', ' + item.zIndex but this doesn't work. 我已经尝试添加+ ', ' + item.zIndex但这不起作用。

The sorting function: 排序功能:

sortItemsArrayByZIndex() {
    this.items.sort((i1, i2) => {
        return (i1.zIndex - i2.zIndex);
    });
}

So it seems that trackBy and this sort function are in conflict for some reason. 所以似乎trackBy和这种排序函数由于某种原因而发生冲突。 The result now is that when i use the sort function the the items array gets sorted according to z-index but the items also switch places, which means that their dimensions properties are switched for some reason. 现在的结果是,当我使用sort函数时,items数组根据z-index进行排序,但项目也会切换位置,这意味着它们的维度属性由于某种原因而被切换。

What i want is that the items array is sorted according to z-index but that the items keep their dimensions. 我想要的是items数组根据z-index排序,但项目保持其尺寸。

How do i need to change my trackBy function or my sort function so that i get the result that i want? 我如何更改我的trackBy函数或我的排序函数,以便我得到我想要的结果?

If you don't mind, I'll add my own answer to explain why your code wasn't working, since you only provided a working code with no explanation. 如果您不介意,我会添加自己的答案来解释您的代码无效的原因,因为您只提供了一个没有解释的工作代码。

The trackBy function trackBy功能

The trackBy function is made to improve performances, and to avoid unecessary change detection. trackBy功能用于改善性能,并避免不必要的变化检测。 You can provide a custom function, as you did, and it will create a value that will be checked to see if the change detection need to be triggered. 您可以像提供的那样提供自定义功能,它将创建一个值,以便检查是否需要触发更改检测。

The issue 问题

Your trackBy function was this : 你的trackBy函数是这样的:

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

This will return a value of this type : 这将返回此类型的值:

90, en-US

Where 90 won't change unless you push/withdraw items from your array , and where en-US can be applied to several items of the array . 除非您从阵列中推送/撤销项目 ,并且en-US 可以应用于阵列的多个项目, 否则 90将不会更改。 This means that if you change either the index or another field, the change detetction won't happen. 这意味着如果更改索引或其他字段,则不会发生更改检测。

The solution 解决方案

Since you want to sort your array, you have to at least add the index to the return of your custom function. 由于您要对数组进行排序,因此必须至少将索引添加到自定义函数的返回值中。 This means that if the index of the item changes (and since you sort your array, it will), the change detection will occur. 这意味着如果项目的索引发生更改(并且由于您对数组进行排序,它将会发生),将发生更改检测。

The minial code would be : 最小代码是:

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

As user @trichetriche mentioned i needed to add the index, and also the zIndex property to the trackBy to let the TrackBy work as intended. 用户@trichetriche提到我需要将索引和zIndex属性添加到trackBy以让TrackBy按预期工作。

The trackBy function looks something like this: trackBy函数看起来像这样:

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM