Угловой трек, возвращающий индекс - PullRequest
0 голосов
/ 01 февраля 2019

У меня огромный ngFor, часто меняющийся с асинхронными данными.TrackBy позволяет обновлять только изменяющуюся часть, и я действительно чувствую разницу, когда добавляю ее.Мне кажется понятным, в чем преимущество, например, отслеживания, возвращающего уникальный идентификатор.Но иногда я вижу образцы, возвращающие текущий индекс.

public trackByFn(index, item) { return index }

В моей таблице я не вижу различий, если я напрямую возвращаю 'index' или 'item.id'.Похоже, что оба оптимизируют рендеринг (но я, возможно, не уловил некоторые ошибочные границы).

Итак, кто-то может объяснить мне, что именно происходит, когда я возвращаю индекс?

1 Ответ

0 голосов
/ 01 февраля 2019

Исходя из вашего комментария и моего собственного любопытства, я покопался в угловом различном коде .Я могу объяснить вам, что происходит в 3 различных сценариях, и я полагаю, что также полезно иметь знания:

Первый сценарий :

Не определено trackBy: <div *ngFor="let obj of arrayOfObj">{{obj.key}}</div>

Если не определено trackBy, угловые итерации по массиву, создание элементов DOM и привязка данных в шаблоне в [ngForOf].(Выше код может быть записан как):

<ng-template ngFor let-obj [ngForOf]="arrayOfObj">
  <div>{{obj.key}}</div>
</ng-template>

Таким образом, в основном, он создает все эти элементы div.Первоначально это одинаково для всех 3 возможностей.Теперь новые данные поступают из API, более или менее те же данные, но ссылка на объект массива изменяется, и все ссылки из объектов в исходном массиве различаются.Если вы не определили функцию trackBy, угловое сравнение выполняется по тождеству ===.Это будет хорошо с строками, числами и другими примитивами (не так много там).Но для объектов этого не будет.Итак, что происходит сейчас, если он начинает проверять, есть ли изменения.Он больше не может найти исходные объекты, поэтому удаляет элементы DOM (фактически сохраняет их где-то для дальнейшего использования, если объект решит вернуться) и создает все шаблоны с нуля.

Даже если данные не изменились, второй ответ создает объекты с разными идентификаторами, и Angular должен разрушить весь DOM и перестроить его (как если бы все старые элементы были удалены и все новые элементы были вставлены) .

Вы можете себе представить, что это может быть довольно жёстким процессором и памятью.

Второй сценарий :

trackBy определенс ключом объекта:

<div *ngFor="let obj of arrayOfObj;trackBy:trackByKey">{{obj.key}}</div>

trackByKey = (index: number, obj: object): string => {
  return object.key;
};

Давайте сделаем это сначала.Это самый быстрый.Таким образом, мы находимся в точке, где поступают новые данные, объекты которых отличаются от прежних.В этот момент angular перебирает все новые объекты над этой функцией trackBy и получает идентификатор объекта.Затем он будет ссылаться на существующие (и ранее удаленные, если не найденные) элементы DOM.Если он найден, он все равно обновит все привязки, сделанные внутри шаблона.Если он не найден, он проверит ранее удаленные объекты, и если он все еще не сможет его найти, он создаст новый элемент DOM из шаблона и обновит привязки.Итак, это быстро.Просто ищите уже созданные элементы DOM и обновляйте привязки, которые угловые могут делать быстро, быстро, быстро.

Третий сценарий :

trackBy, определенный с массивомindex

<div *ngFor="let obj of arrayOfObj;trackBy:trackByIndex">{{obj.key}}</div>

trackByIndex = (index: number): number => {
  return index;
};

Это та же история, что и с ключом объекта trackBy, но с той небольшой разницей, что если вы играете в juggle с элементами внутри массива, привязки в шаблонах продолжают обновляться,Но это все еще быстро, но, скорее всего, не самый быстрый способ :), хотя это намного быстрее, чем воссоздание всего DOM.

Надеюсь, вы почувствуете разницу сейчас.Немного чего-то дополнительного, хотя.Если у вас есть много бизнес-объектов, которые имеют одинаковый способ доступа к своей идентичности, например свойство .id или .key, вы можете расширить нативный *ngFor и создать свою собственную структурную директиву, которая имеет этот trackByВстроенная функция. Непроверенный код:

export interface BaseBo {
  key: string;
}

@Directive({selector: '[boFor][boForOf]'})
export class ForOfDirective<T extends BaseBo> extends NgForOf<T> {
  @Input()
  set boForOf(boForOf: T[]) {
    this.ngForOf = boForOf;
  }

  ngForTrackBy = (index: number, obj: T) => obj.key;
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...