Как key влияет на перерендеринг шаблона во Vue
Что проверяют
Понимаете ли вы, что key задаёт идентичность узла для алгоритма сравнения виртуального DOM, а не служит украшением v-for. Следом обычно спрашивают, чем плох индекс в роли ключа и как с помощью key сбросить состояние компонента.
Как отвечать
При обновлении Vue сравнивает старый и новый списки дочерних узлов:
- без
key: работает стратегия «патча на месте». Элементы переиспользуются по позиции, меняется только содержимое. Это дёшево, но корректно лишь тогда, когда у элементов нет своего состояния: значения в<input>, фокуса, локального состояния дочернего компонента; - с
key: Vue сопоставляет узлы по ключу, переставляет существующие DOM-элементы, создаёт новые и удаляет те, чьих ключей больше нет. Состояние едет вместе с элементом; - смена
keyу одного элемента: старый экземпляр размонтируется, новый монтируется заново. Этим пользуются намеренно:<UserForm :key="userId" />сбрасывает форму при смене пользователя, а смена ключа внутри<Transition>запускает анимацию.
Требования к ключу: уникален среди соседей, примитив (строка или число), стабилен между рендерами. Лучше всего подходит id из данных. Две детали Vue 3: у <template v-for> ключ ставится на сам <template>, а ветки v-if/v-else получают уникальные ключи автоматически, поэтому ручные ключи там больше не нужны. Отсутствие ключа в v-for ловит правило vue/require-v-for-key из eslint-plugin-vue.
Где спотыкаются
Ставят индекс. При удалении элемента из середины ключи сдвигаются, и введённый текст или раскрытое состояние переезжает к соседней строке.
Говорят, что key ускоряет рендер. Для простого списка без состояния патч на месте как раз дешевле, ключ нужен ради правильности.
Генерируют ключ на лету через Math.random() или Date.now(). Каждый рендер пересоздаёт все элементы: теряется фокус, а список из тысячи строк начинает тормозить.