Как правильно использовать ключ (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, чтобы при сравнении старого и нового дерева:
-
Найти соответствие между старым и новым элементом.
-
Принять решение: нужно ли обновлять элемент, переместить или удалить.
-
Не обновлять те элементы, которые остались прежними.
-
Быстро удалить/добавить только изменившиеся элементы.
Это даёт производительность и точность.
Ошибки и рекомендации
-
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 с интерактивными компонентами и динамическими списками.