Официальный ответ заключается в том, что вы используете trackBy
, чтобы избежать воссоздания элементов в DOM для новых экземпляров объектов с одинаковым идентификатором.
На первый взгляд, ваша установка не доказывает, что ngFor
не просто игнорирует значение undefined
, которое вы возвращаете в trackByFn
, и воссоздает элементы DOM в любом случае, когда в модели появляются новые экземпляры.
Новые элементы с тем же идентификатором, что и существующие объекты, могут изменились другие свойства, поэтому можно ожидать, что HTML будет правильным независимо от того, используете ли вы (или неправильно) trackBy
.
Настройка
, которую я создал тестовая среда, использующая ваш код, за исключением того, что я разветвил исходный код для *ngFor
, чтобы я мог добавить собственную регистрацию, чтобы отслеживать, что происходит внутри *ngFor
.
Я тестировал три сценария ios:
A) trackByFn
возвращает уникальный идентификатор
B) trackByFn
возвращает undefined
C) не использует trackBy
Я проследил, что происходит в каждом сценарии для следующих шагов
* 1 031 * создать список частично заменить некоторые данные списка список сортировки сбросить данные списка
Я назначил новые экземпляры объектов на каждом шаге для «чистого» теста.
Результаты
1. создать список
То же самое для всех 3 сценариев ios - элемент DOM создается для каждого элемента в списке.
2. частично заменить некоторые данные списка
A) удаляет элементы DOM для удаленных элементов и создает новые элементы DOM для новых элементов. Все элементы обновляются.
B) создает новые элементы DOM для элементов с индексом за пределами исходного массива. Все элементы обновляются.
C) воссоздает все элементы DOM.
3. список сортировки
A) перемещает элементы DOM, которые сместили позиции
B) обновляет элементы DOM, которые сместили позиции
C), воссоздает все DOM элементы
4. сбросить список данных
A) удаляет элементы DOM для удаленных элементов и создает новые элементы DOM для новых элементов. Все элементы обновляются (как в сценарии 2).
B) удаляет элементы DOM для удаленных элементов. Все элементы обновляются.
C) воссоздает все элементы DOM.
Выводы
Важно отметить, что эти тесты были выполнены с использованием новых экземпляров объектов. *ngFor
более эффективен, если вы повторно используете ссылки на объекты.
Использование trackBy
более эффективно с точки зрения манипулирования DOM, если у вас очень изменчивый список.
Удивительно результат
Из моих тестов выясняется, что ваш пример выполняет меньше манипуляций с DOM, чем при возврате уникального идентификатора из trackByFn
. Если вы замените 3 элемента на 3 новых, ваш метод не будет манипулировать DOM и все равно будет запускать тот же метод обновления, что и «правильный» способ. «Правильный» метод удалит исходные 3 элемента DOM и добавит 3 новых элемента DOM.
Это говорит о том, что мы могли бы просто предоставить trackByFn
, который возвращает постоянное значение без каких-либо неожиданных результатов. Из-за того, что я просмотрел исходный код и поиграл с ним, я не могу понять, в чем проблема (кроме того, что он сбивает с толку других людей, которые смотрят на ваш код).
Это заставляет меня задуматься, почему значение по умолчанию Реализация должна воссоздать все элементы DOM, когда повторное использование старых элементов DOM работает нормально. Я уверен, что есть некоторые случаи, которые я не рассматривал, и я хотел бы услышать их.
DEMO: https://stackblitz.com/edit/angular-anejhw
Это превратилось в немного «веселой» исследовательской задачи, а не однозначного ответа, но, надеюсь, она окажется полезной. Несмотря на то, что я показал, что возвращение константного значения из trackByFn
представляется наиболее эффективным вариантом, я все равно буду колебаться при использовании этого подхода в рабочем коде. Даже если теперь это работает для всех случаев, я не удивлюсь, если это будет исправлено в какой-то момент как ошибка.
ngForOf
исходный код: https://github.com/angular/angular/blob/master/packages/common/src/directives/ng_for_of.ts