Как правильно использовать ключ (key) при рендеринге списков?

Во Vue ключ (key) при рендеринге списков используется для однозначной идентификации элементов в цикле v-for, чтобы Vue мог корректно отслеживать изменения, повторно использовать существующие DOM-элементы и эффективно обновлять виртуальный DOM. Использование правильного ключа критично для производительности, предсказуемости поведения и отсутствия визуальных багов в интерфейсе.

Почему key важен

Vue использует виртуальный DOM — абстрактное представление DOM-дерева. Когда данные изменяются, Vue сравнивает предыдущее виртуальное дерево с новым и определяет, какие DOM-элементы нужно обновить. Без key он сравнивает элементы "вслепую", по порядку, что может приводить к ошибкам: например, Vue может не создать новый элемент, а обновить существующий не там, где нужно.

key помогает Vue точно сопоставить виртуальные элементы со старыми элементами DOM, избегая избыточного рендера и багов.

Простой пример

<li v-for="item in items" :key="item.id">
{{ item.name }}
</li>

Если в массиве items изменится порядок или появится новый элемент, Vue использует item.id, чтобы понять, что это именно другой объект, и обновит DOM корректно.

Ошибки при отсутствии или неправильном ключе

Пример без key:

<li v-for="item in items">{{ item.name }}</li>

Vue не сможет правильно отследить, какой элемент был изменён, а какой остался прежним. Это может привести к:

  • Повторному созданию DOM-элементов, даже если они не изменились.

  • Потере состояния компонента (например, фокуса ввода, анимации, состояний чекбоксов).

  • Неправильной анимации (переходы будут странно работать).

  • Нарушению логики работы вложенных компонентов.

Какой key правильный

Уникальный идентификатор (желательно из данных)

Если у вас в массиве есть уникальный id (например, user.id или item.uuid), его и нужно использовать:

<div v-for="user in users" :key="user.id">
{{ user.name }}
</div>

Такой key остаётся стабильным между рендерами и позволяет Vue точно отследить, какой элемент поменялся.

Использовать индекс — только в крайних случаях

<li v-for="(item, index) in items" :key="index">
{{ item.name }}
</li>

Использование индекса допустимо только, если:

  • Список статичен и не будет изменяться.

  • Не будет добавления/удаления/перетасовки элементов.

  • Элементы не содержат компонентов со своим внутренним состоянием (например, форма с вводом, переключатели).

Почему индекс может быть плохим ключом:

  • При добавлении нового элемента в начало списка все индексы сдвинутся, и Vue решит, что каждый элемент — новый, удалит старые и создаст заново.

  • Состояния компонентов могут быть нарушены (например, текст в поле ввода исчезнет).

  • Анимации будут некорректными (прыжки, мерцание).

Примеры ситуаций, где key критически важен

Динамическое удаление элементов

<ul>
<li v-for="todo in todos" :key="todo.id">
{{ todo.text }}
<button @click="remove(todo.id)">Удалить</button>
</li>
</ul>

Если key не использовать, при удалении Vue может случайно обновить не тот элемент, особенно если список длинный.

Форма с вводом

<input v-for="item in items" :key="item.id" v-model="item.text" />

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

Компоненты в списке

<custom-item v-for="item in items" :key="item.id" :data="item" />

Компоненты имеют свой жизненный цикл. Без key Vue может не переиспользовать правильный экземпляр компонента, а удалить старый и создать новый, что нарушает поведение, например:

  • mounted() будет вызываться снова.

  • Пропадёт локальное состояние (data, ref, watch).

  • Анимации могут быть некорректны.

Как key работает внутри

Vue строит виртуальное дерево DOM и использует key, чтобы при сравнении старого и нового дерева:

  1. Найти соответствие между старым и новым элементом.

  2. Принять решение: нужно ли обновлять элемент, переместить или удалить.

  3. Не обновлять те элементы, которые остались прежними.

  4. Быстро удалить/добавить только изменившиеся элементы.

Это даёт производительность и точность.

Ошибки и рекомендации

  • key должен быть уникальным в рамках текущего v-for. Повторяющиеся ключи вызовут предупреждения и баги.

  • key должен быть стабильным — не меняться между рендерами.

  • Не используйте случайные ключи, вроде Math.random() или Date.now() — каждый раз Vue будет считать элемент новым.

  • Нельзя полагаться на индекс, если список может меняться.

Ключ — не только Vue

Концепция key не уникальна для Vue. Она присутствует и в других фреймворках, таких как React, потому что это стандартный способ помочь виртуальному DOM отслеживать и повторно использовать элементы.

Пример: неправильное поведение без key

data() {
return {
users: \[
{ id: 1, name: 'Аня' },
{ id: 2, name: 'Борис' }
\]
}
}

Выводим поля ввода:

<div v-for="user in users">
<input v-model="user.name" />
</div>

Если теперь вставить нового пользователя в начало:

this.users.unshift({ id: 3, name: 'Катя' })

Vue без key может неправильно сопоставить элементы и перезаписать имена.

Вывод из практики

  • key должен быть обязательным при использовании v-for.

  • Лучший key — уникальный идентификатор, присутствующий в самих данных.

  • Никогда не используйте Math.random(), индексы или неуникальные значения в key.

  • Вложенные v-for также требуют key для каждой итерации.

Правильное использование key — это не просто рекомендация, а базовый принцип эффективного рендеринга во Vue, особенно в сложных UI с интерактивными компонентами и динамическими списками.