Списки: v-for и key

Выводим списки данных в разметку через директиву v-for и разбираемся, почему атрибут key — не формальность, а важная вещь для производительности.

v-for — директива, которая повторяет элемент шаблона для каждого элемента массива или каждого свойства объекта.

Перебор массива

Синтаксис v-for="item in items" создаёт по одному элементу на каждый item. К каждому элементу нужно добавить уникальный :key:

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

<script setup>
import { ref } from 'vue'
const users = ref([
  { id: 1, name: 'Аня' },
  { id: 2, name: 'Борис' },
  { id: 3, name: 'Вера' },
])
</script>

Доступ к индексу

Вторым параметром v-for отдаёт индекс элемента:

<template>
  <ol>
    <li v-for="(user, index) in users" :key="user.id">
      {{ index + 1 }}. {{ user.name }}
    </li>
  </ol>
</template>

Зачем нужен key

Когда список меняется (добавили, удалили, переставили элемент), Vue нужно понять, какой DOM-узел какому данному соответствует. Атрибут key — это стабильный идентификатор каждого элемента. По нему Vue точно знает: «это тот же элемент, что был, просто сдвинулся» — и переиспользует существующий узел вместо пересоздания.

Без key (или с индексом массива в роли ключа) Vue сопоставляет элементы по позиции. При вставке в начало списка это приводит к лишним обновлениям, а в формах — к багам: введённый текст «перескакивает» не на ту строку. Поэтому в ключ ставьте стабильный уникальный id из данных, а не индекс.

Проверим логику ключей на JS

Уникальность id легко прочувствовать обычным кодом. Сделаем «ключи» из массива объектов и убедимся, что они уникальны:

const users = [
  { id: 101, name: "Аня" },
  { id: 102, name: "Борис" },
  { id: 103, name: "Вера" },
];

const keys = users.map(u => u.id);
console.log("Ключи:", keys);
console.log("Все уникальны:", new Set(keys).size === keys.length);

Вывод:

Ключи: [ 101, 102, 103 ]
Все уникальны: true

Частые ошибки

ОшибкаПочему плохо
Нет :keyVue ругается в консоли, возможны баги при изменении списка
:key="index"при вставке/удалении ключи «съезжают», ломая привязку
Изменение длины массива через arr[5] = xлучше использовать push, splice — они реактивны

Итог

  • v-for="item in items" повторяет элемент для каждого элемента массива.
  • Вторым параметром доступен индекс: (item, index).
  • :key обязателен — это стабильный id для эффективного обновления DOM.
  • В ключ ставьте уникальный id из данных, а не индекс массива.
Проверьте себя
1. Как с помощью v-for получить доступ к индексу элемента?
Av-for="index in items"
Bv-for="(item, index) in items"
Cv-for="item.index in items"
Dv-for="item with index"
2. Зачем v-for требует атрибут :key?
AЧтобы стилизовать элементы списка
BЧтобы дать Vue стабильный id каждого элемента для корректного и эффективного обновления DOM
CЭто нужно только для нумерованных списков
Dkey хранит данные элемента
3. Почему не стоит использовать индекс массива в качестве :key?
AИндекс — это строка, а нужно число
BПри вставке или удалении элементов индексы «съезжают», что ломает привязку DOM к данным
CVue запрещает числовые ключи
DИндекс работает медленнее, чем id
Поддержать проект