Списки: v-for и key
Директива v-for повторяет элемент для каждого значения массива. Вместо цикла, который создаёт элементы через createElement, вы описываете один элемент, а Vue выводит столько, сколько записей в данных.
Вывод массива
<!-- src/App.vue -->
<script setup>
import { ref } from 'vue'
const todos = ref([
{ id: 1, text: 'Купить хлеб', done: true },
{ id: 2, text: 'Позвонить Анне', done: false },
{ id: 3, text: 'Написать отчёт', done: false },
])
</script>
<template>
<ul>
<li v-for="todo in todos" :key="todo.id">
{{ todo.text }}
</li>
</ul>
</template>На странице появится список из трёх задач. Запись todo in todos похожа на for...of: переменная todo по очереди принимает каждую задачу и доступна внутри li.
Атрибут key
:key — уникальный ключ элемента. По нему Vue понимает, какой элемент DOM соответствует какой записи, когда список меняется: при удалении задачи из середины он уберёт ровно её li, а не перерисует все строки. В качестве ключа берите id из данных — строку или число, которые не повторяются.
Индекс
Второй переменной в скобках можно получить номер элемента:
<template>
<ul>
<li v-for="(todo, index) in todos" :key="todo.id">
{{ index + 1 }}. {{ todo.text }}
</li>
</ul>
</template>Строки получат номера: «1. Купить хлеб», «2. Позвонить Анне» и так далее. Нумерация начинается с нуля, поэтому к индексу прибавляется единица.
Изменение списка
Список на странице обновляется, когда меняется массив:
<script setup>
import { ref } from 'vue'
const todos = ref([
{ id: 1, text: 'Купить хлеб', done: false },
{ id: 2, text: 'Позвонить Анне', done: false },
])
function removeTodo(id) {
todos.value = todos.value.filter((todo) => todo.id !== id)
}
</script>
<template>
<ul>
<li v-for="todo in todos" :key="todo.id">
{{ todo.text }}
<button @click="removeTodo(todo.id)">Удалить</button>
</li>
</ul>
</template>Кнопка «Удалить» убирает свою задачу: обработчик получает id из текущей итерации цикла.
Другие источники
| Запись | Что перебирается |
|---|---|
v-for="todo in todos" | Элементы массива |
v-for="n in 5" | Числа от 1 до 5 |
v-for="(value, key) in user" | Значения и ключи объекта |
Отфильтрованный список выводят через computed из урока про вычисляемые свойства: v-for="todo in visibleTodos".
Частая ошибка
Ставить v-if и v-for на один элемент:
<li v-for="todo in todos" v-if="!todo.done" :key="todo.id">
{{ todo.text }}
</li>v-if выполняется раньше v-for, и переменной todo в нём ещё нет — Vue выдаст ошибку. Отфильтруйте список в computed или перенесите v-for на обёртку template, а v-if оставьте на li.