Сортировка массива *ngFor с помощью trackBy в Angular 4

У меня проблемы с сортировкой и массивом, который имеет функцию trackBy. Вариант использования выглядит следующим образом:

У меня есть массив элементов. Все эти элементы имеют свойство z-index. У меня также есть менеджер слоев, который может редактировать z-индекс каждого элемента. Когда я хочу сохранить свои элементы, я хочу отсортировать массив в соответствии со свойством z-index каждого элемента. У меня также есть trackBy на моем ngFor, чтобы ограничить количество обнаруженных изменений на *ngFor.

С функцией trackBy на моем * ngFor элементы меняются местами, когда я сортирую массив (что плохо). Если я удалю функцию 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 и эта функция сортировки почему-то конфликтуют. В результате теперь, когда я использую функцию сортировки, массив элементов сортируется в соответствии с z-индексом, но элементы также меняются местами, что означает, что их свойства измерений по какой-то причине переключаются.

Я хочу, чтобы массив items сортировался в соответствии с z-index, но чтобы элементы сохраняли свои размеры.

Как мне нужно изменить мою функцию trackBy или функцию сортировки, чтобы я получил желаемый результат?

2 ответа

Решение

Если вы не возражаете, я добавлю свой собственный ответ, чтобы объяснить, почему ваш код не работал, поскольку вы предоставили только рабочий код без объяснения причин.

Функция trackBy

Функция trackBy предназначена для повышения производительности и предотвращения ненужного обнаружения изменений. Вы можете предоставить пользовательскую функцию, как вы это сделали, и она создаст значение, которое будет проверяться, чтобы увидеть, нужно ли запускать обнаружение изменений.

Проблема

Ваша функция trackBy была такой:

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

Это вернет значение этого типа:

90, en-US

куда 90 не изменится, пока вы не вытолкнете / не удалите элементы из массива и не en-US может применяться к нескольким элементам массива. Это означает, что если вы измените индекс или другое поле, обнаружение изменений не произойдет.

Решение

Поскольку вы хотите отсортировать ваш массив, вы должны как минимум добавить индекс к возврату вашей пользовательской функции. Это означает, что если индекс элемента изменяется (и поскольку вы сортируете свой массив, он будет изменяться), обнаружение изменений произойдет.

Минский код будет:

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

Как отметил пользователь @trichetriche, мне нужно было добавить индекс, а также свойство zIndex в trackBy, чтобы позволить TrackBy работать так, как задумано.

Функция trackBy выглядит примерно так:

getUniqueIdentifier(index, item) {
    return index + ', ' + item.zIndex + ', ' + this.languages._previewLanguage + ', ' + this.items.length;
}
Другие вопросы по тегам