Работа с данными в приложении часто сводится к выводу списков. Это могут быть карточки товаров в интернет-магазине, посты в блоге или комментарии к статье. Когда данные представлены в виде массива или объекта, нам нужно уметь грамотно их отображать на странице.
В этой статье мы погрузимся в отрисовку списков в Vue 3, используя директиву v-for, разберём типичные сценарии и важные нюансы, которые стоит учитывать.
Основы директивы v-for
Vue предоставляет очень удобную директиву v-for, с помощью которой можно выводить элементы массива или свойства объектов в виде списка. Директива работает по аналогии с циклами в обычных языках программирования: она итерирует по данным и выводит каждый элемент или ключ-значение объекта.
Простой пример с массивом:
<template>
<ul>
<li v-for="item in items" :key="item.id">{{ item.name }}</li>
</ul>
</template>
<script setup>
import { ref } from 'vue';
const items = ref([
{ id: 1, name: 'Apple' },
{ id: 2, name: 'Banana' },
{ id: 3, name: 'Orange' }
]);
</script>
Здесь мы выводим список фруктов. Для каждого элемента массива items создаётся отдельный li элемент. Обратите внимание на использование атрибута :key. Это обязательный параметр при работе с v-for, чтобы Vue мог эффективно отслеживать изменения в списке и обновлять DOM.
Индекс элементов в v-for
Иногда, кроме данных, нам нужно использовать индекс элемента в списке. Vue легко позволяет это сделать, просто передав дополнительный параметр в цикл:
<template>
<ul>
<li v-for="(item, index) in items" :key="index">{{ index + 1 }}. {{ item.name }}</li>
</ul>
</template>
<script setup>
const items = ref(['Item 1', 'Item 2', 'Item 3']);
</script>
Теперь вместе с именем каждого элемента будет выводиться его порядковый номер. Важно отметить, что использование индекса как key не всегда хорошая практика, особенно если данные могут изменяться. В таких случаях уникальные идентификаторы гораздо надёжнее.
Отрисовка объектов
Если вам нужно вывести объект, а не массив, v-for тоже подойдёт. Директива позволяет итерировать по ключам объекта.
Пример:
<template>
<ul>
<li v-for="(value, key) in user" :key="key">{{ key }}: {{ value }}</li>
</ul>
</template>
<script setup>
const user = ref({
name: 'John Doe',
email: 'john@example.com',
age: 30
});
</script>
Здесь мы выводим свойства объекта user. На каждом шаге цикла получаем ключ (например, name, email, age) и значение этого ключа. Это полезно, когда вам нужно отобразить данные объекта в виде списка.
Вложенные циклы
Что делать, если у вас массив, внутри которого находятся другие массивы? Или объект с массивами? Vue позволяет использовать вложенные циклы для таких случаев. Представим, что у нас есть массив заказов, и каждый заказ содержит список товаров:
<template>
<ul>
<li v-for="order in orders" :key="order.id">
Заказ #{{ order.id }}
<ul>
<li v-for="product in order.products" :key="product.id">
{{ product.name }} - {{ product.quantity }} шт.
</li>
</ul>
</li>
</ul>
</template>
<script setup>
const orders = ref([
{
id: 1,
products: [
{ id: 101, name: 'Товар 1', quantity: 2 },
{ id: 102, name: 'Товар 2', quantity: 1 }
]
},
{
id: 2,
products: [
{ id: 103, name: 'Товар 3', quantity: 4 },
{ id: 104, name: 'Товар 4', quantity: 3 }
]
}
]);
</script>
Здесь мы выводим список заказов, внутри которых находится ещё один список товаров. Вложенные циклы позволяют нам работать с любой структурой данных, какой бы сложной она ни была.
Условная отрисовка внутри v-for
Иногда вам нужно не просто вывести список, но и отфильтровать данные перед их показом. Например, вы хотите отобразить только активные элементы. Это легко можно сделать, комбинируя директиву v-if с циклом:
<template>
<ul>
<li v-for="item in items" v-if="item.active" :key="item.id">{{ item.name }}</li>
</ul>
</template>
<script setup>
const items = ref([
{ id: 1, name: 'Task 1', active: true },
{ id: 2, name: 'Task 2', active: false },
{ id: 3, name: 'Task 3', active: true }
]);
</script>
Здесь мы выводим только активные задачи, то есть те, у которых свойство active равно true.
Однако важно помнить, что использование v-if вместе с v-for может привести к дополнительным затратам на рендеринг. Если вам нужно скрыть неактивные элементы, возможно, лучше сначала отфильтровать данные перед их выводом:
<template>
<ul>
<li v-for="item in activeItems" :key="item.id">{{ item.name }}</li>
</ul>
</template>
<script setup>
import { computed, ref } from 'vue';
const items = ref([
{ id: 1, name: 'Task 1', active: true },
{ id: 2, name: 'Task 2', active: false },
{ id: 3, name: 'Task 3', active: true }
]);
const activeItems = computed(() => items.value.filter(item => item.active));
</script>
Такой подход позволяет улучшить производительность за счёт того, что Vue будет работать только с уже отфильтрованными данными.
Пустые списки
В реальных приложениях иногда возникает ситуация, когда массив данных пуст. Хорошим тоном будет сообщить пользователю, что данных пока нет, вместо того чтобы просто оставлять пустое место на экране. Это можно легко реализовать с помощью условной отрисовки:
<template>
<div>
<p v-if="!items.length">Список пуст.</p>
<ul v-else>
<li v-for="item in items" :key="item.id">{{ item.name }}</li>
</ul>
</div>
</template>
<script setup>
const items = ref([]);
</script>
В этом примере, если массив items пуст, выводится сообщение «Список пуст». В противном случае будет отображён список элементов.
Заключение
Отрисовка списков — одна из ключевых задач в любом веб-приложении, и Vue.js предоставляет мощный и удобный механизм для работы с массивами и объектами. Мы рассмотрели, как использовать директиву v-for, как работать с индексами и ключами, как выводить вложенные списки и даже как обрабатывать пустые массивы.
В следующий раз мы разберём более сложные сценарии работы с динамическими данными и отрисовкой элементов на лету. Оставайтесь с нами!