v-for — директива для рендеринга списков во Vue. Она создаёт элементы на основе массива или объекта. Атрибут :key необходим для корректной идентификации элементов при обновлении списка.
Ключевые аспекты
Итерация по массиву — v-for="item in items" или v-for="(item, index) in items"
Итерация по объекту — v-for="(value, key, index) in object"
Итерация по диапазону — v-for="n in 10" создаст 10 элементов
Обязательный key — уникальный идентификатор для каждого элемента
Работа с template — группировка нескольких элементов в цикле
Плюсы
Декларативный синтаксис для рендеринга списков
Автоматическое обновление при изменении данных
Оптимизация рендеринга через key
Поддержка деструктуризации в выражениях
Минусы
Требуется уникальный key для оптимальной производительности
Нельзя комбинировать с v-if на одном элементе
Использование index как key может привести к багам
Частые ошибки на собеседованиях
Не понимают зачем нужен key (для идентификации элементов при reconciliation)
Используют index как key для динамических списков (приводит к багам при сортировке/удалении)
Путают синтаксис in и of (оба работают одинаково)
Не знают, что v-for может работать с объектами и числами, не только с массивами
Введение и проблематика
Отображение списков — одна из базовых задач в веб-разработке:
Список товаров в каталоге
Посты в ленте
Элементы меню навигации
Строки таблицы
Vue предоставляет директиву v-for для декларативного рендеринга коллекций данных.
Атрибут key критически важен для производительности и корректной работы Vue. Он помогает Vue понять, какие элементы изменились, добавились или удалились.
<template> <ul><!-- Только значения --> <liv-for="value in profile":key="value"> {{ value }} </li><!-- Значение и ключ --> <liv-for="(value, key) in profile":key="key"> {{ key }}: {{ value }} </li><!-- Значение, ключ и индекс --> <liv-for="(value, key, index) in profile":key="key"> {{ index }}. {{ key }}: {{ value }} </li> </ul></template><scriptsetup>import { reactive } from'vue'constprofile=reactive({ name:'Иван', age:25, city:'Москва'})</script>
Итерация по диапазону чисел
vue
<template><!-- Создаёт 5 элементов (n от 1 до 5) --> <spanv-for="n in 5":key="n">{{ n }} </span><!-- Результат: 1 2 3 4 5 --></template>
<template><!-- ❌ Не рекомендуется --> <liv-for="item in items"> {{ item.name }} </li></template>
Vue использует алгоритм «по месту» (in-place patch)
При изменении порядка состояние компонентов не сохраняется
Могут быть баги с анимациями и формами
Правила для key
vue
<template><!-- ✅ Уникальный идентификатор из данных --> <liv-for="user in users":key="user.id"><!-- ✅ Уникальная комбинация --> <liv-for="item in items":key="`${item.type}-${item.id}`"><!-- ❌ Index для динамических списков --> <liv-for="(item, index) in items":key="index"><!-- ❌ Неуникальные значения --> <liv-for="item in items":key="item.name"></template>
⚠️
Используйте index как key только для статических списков, которые не будут изменяться (сортировка, фильтрация, добавление в середину).
Пограничные кейсы
v-if и v-for
🚫
Не используйте v-if и v-for на одном элементе. v-if имеет приоритет выше и не видит переменные из v-for.
<template> <divv-for="category in categories":key="category.id"> <h3>{{ category.name }}</h3> <ul> <liv-for="item in category.items":key="item.id"> {{ item.name }} </li> </ul> </div></template>
Мутации массива
Vue отслеживает мутирующие методы массива и реактивно обновляет DOM:
vue
<scriptsetup>import { ref } from'vue'constitems=ref(['A','B','C'])// Эти методы вызовут обновлениеitems.value.push('D') // добавить в конецitems.value.pop() // удалить с концаitems.value.shift() // удалить с началаitems.value.unshift('Z') // добавить в началоitems.value.splice(1,1) // удалить/вставитьitems.value.sort() // сортировкаitems.value.reverse() // реверс</script>
Для замены массива присвойте новое значение:
vue
<scriptsetup>// Фильтрация — создаёт новый массивitems.value =items.value.filter(item =>item.isActive)// Маппингitems.value =items.value.map(item => ({ ...item, processed:true }))</script>
Плюсы и минусы
Аспект
v-for с key
Без key
Производительность
Оптимальная
Может быть хуже
Состояние компонентов
Сохраняется
Теряется
Сортировка списка
Корректная
Баги
Анимации
Работают
Могут сломаться
Формы в списке
Корректные
Данные путаются
Вопросы интервьюера
Q: Зачем нужен атрибут key?
Key помогает Vue идентифицировать элементы при обновлении списка. Без key Vue использует алгоритм «по месту», который может привести к багам при изменении порядка или удалении элементов.
Q: Можно ли использовать index как key?
Только для статических списков. Для динамических (с сортировкой, фильтрацией, добавлением) нужен уникальный идентификатор из данных.
Q: Почему нельзя использовать v-if и v-for вместе?
v-if имеет более высокий приоритет и вычисляется первым, не имея доступа к переменным из v-for. Используйте computed или оберните в template.
Q: Какие методы массива вызывают обновление?
Мутирующие методы: push, pop, shift, unshift, splice, sort, reverse. Они отслеживаются Vue и вызывают ререндер.