Олег Марков
Использование массивов и их обработка в Vue
Введение
Массивы — это основа для хранения коллекций данных практически в любом приложении, и во Vue они используются очень часто. Например, список задач, карточки товаров или сообщения чата — всё это реализуется и хранится в массивах. Грамотная работа с массивами и их обработка позволяют не только отображать данные, но и обновлять их, отслеживать изменения, фильтровать и сортировать — причем всё это делается реактивно, с мгновенным обновлением интерфейса.
В этой статье вы детально познакомитесь с тем, как работают массивы во Vue. Мы разберём, чем массивы во Vue отличаются от «обычных» в JavaScript, как правильно отображать элементы в шаблоне, обновлять данные, применять сортировки и фильтры, какие «подводные камни» есть при их изменении и как добиться корректной реактивности во всех случаях.
Работа с массивами во Vue: основы
Где встречаются массивы в проектах на Vue
В большинстве приложений на Vue массивы хранятся либо в состоянии компонента (через data), либо приходят с сервера (через props или store). Например:
- список пользователей,
- массив задач,
- список товаров,
- сообщения и комментарии.
Почти всегда эти списки отображаются через директиву v-for, а для вычисления отображаемых данных часто используются вычисляемые свойства (computed) или методы.
Инициализация массивов в data компонента
Вот пример, как объявить массив в data:
export default {
data() {
return {
tasks: [
{ id: 1, text: 'Почитать документацию', done: false },
{ id: 2, text: 'Сделать домашнее задание', done: true }
]
}
}
}
Массив tasks
теперь реактивный, любые его изменения автоматически обновят отображение компонента.
Как отобразить массив в шаблоне с помощью v-for
Пример базового отображения
Вам, скорее всего, нужно вывести все элементы массива на страницу. Для этого используется директива v-for:
<ul>
<li v-for="task in tasks" :key="task.id">
{{ task.text }}
</li>
</ul>
v-for="task in tasks"
— означает, что для каждого элемента массива будет создан элемент в DOM.:key="task.id"
— Vue рекомендует использовать уникальный идентификатор как ключ для правильного трекинга изменений.
Обратите внимание: всегда используйте
:key
для корректного обновления DOM!
Как работает обновление DOM при изменениях массива
Когда изменяется массив (удаление, добавление элементов), Vue отслеживает их по key
и эффективно обновляет только нужные элементы в DOM без перерисовки всего списка.
Обработка массивов: добавление, удаление, изменение
Добавление элементов
Добавить элемент можно стандартными методами массива, например, через push
:
this.tasks.push({ id: 3, text: 'Изучить работу с массивами', done: false })
// Новый элемент добавлен, список в шаблоне обновится автоматически
Удаление элементов
Удалить элемент можно по индексу с помощью splice
:
// Удалить второй элемент
this.tasks.splice(1, 1)
Если вам нужно найти объект по условию, используйте методы массива:
const index = this.tasks.findIndex(task => task.id === 2)
if (index !== -1) {
this.tasks.splice(index, 1)
}
Изменение элементов
Реактивность массивов во Vue имеет особенности: Vue отслеживает только операции, которые явно видны (например, push
, splice
), но если вы напрямую присвоите значение по индексу, реактивность может не сработать:
// Этот способ не реактивен!
// this.tasks[0] = { ... }
this.$set(this.tasks, 0, { id: 1, text: 'Новое значение', done: false })
// Или в Vue 3:
this.tasks[0] = { id: 1, text: 'Новое значение', done: false }
// В Vue 3 реактивность будет работать корректно в обоих случаях
Важный момент: в Vue 2 напрямую менять элементы по индексу (через []) не рекомендуется — используйте
Vue.set
илиthis.$set
. В Vue 3 реактивность работает корректно и при прямом присваивании.
Реактивность при работе с массивами
Почему «не видит» изменения?
Vue 2 имеет ограничения из-за особенностей реализации реактивности через Object.defineProperty:
- Не «видит» изменение длины массива — если вы просто замените массив на новый, реактивности не будет без перезаписи через this.tasks = [...newArray]
- Не отслеживает изменения, если заменить элемент по индексу: this.tasks[0] = ...
- Не «видит» прямое изменение длины: this.tasks.length = 0
Для этих случаев используйте:
Vue.set(this.tasks, idx, newValue)
— для замены элемента по индексу,this.tasks.splice(...)
— для удаления/добавления/замены элементов,- перезаписывайте весь массив:
this.tasks = this.tasks.filter(...)
или с помощью spreadthis.tasks = [...this.tasks]
.
В Vue 3 эти ограничения сняты благодаря Proxy.
Пример замены массива целиком: фильтрация
// Допустим, хотим оставить только завершённые задачи
this.tasks = this.tasks.filter(task => task.done)
// Это заменит массив, и компонент перерисуется
Фильтрация и сортировка массивов во Vue
Использование вычисляемых свойств (computed)
Один из лучших способов предоставить пользователю разные «срезы» массива — вычисляемые свойства.
Давайте добавим фильтр по выполненным задачам и сортировку по алфавиту:
export default {
data() {
return {
tasks: [
{ id: 1, text: 'Проверить почту', done: false },
{ id: 2, text: 'Сходить в магазин', done: true }
],
search: '',
showDone: false
}
},
computed: {
filteredTasks() {
let tasks = this.tasks
if (this.search) {
tasks = tasks.filter(task =>
task.text.toLowerCase().includes(this.search.toLowerCase())
)
}
if (this.showDone) {
tasks = tasks.filter(task => task.done)
}
// Сортировка по алфавиту
return tasks.slice().sort((a, b) => a.text.localeCompare(b.text))
}
}
}
В шаблоне:
<ul>
<li v-for="task in filteredTasks" :key="task.id">
{{ task.text }}
</li>
</ul>
filteredTasks
— изменяется автоматически, когда изменяетсяtasks
,search
илиshowDone
.- Используйте slice() перед сортировкой, чтобы не мутировать исходный массив (sort() мутирует массив!).
Передача параметров в методы для фильтрации/сортировки
Иногда фильтрация зависит от параметра, который задается динамически. В этом случае используйте методы:
methods: {
byStatus(done) {
return this.tasks.filter(task => task.done === done)
}
}
И вызывайте в шаблоне:
<ul>
<li v-for="task in byStatus(true)" :key="task.id">
{{ task.text }}
</li>
</ul>
Массивы объектов и их обновление
Изменение свойств объекта внутри массива
Когда вы редактируете свойство объекта внутри массива, Vue отслеживает это изменение и корректно обновляет DOM:
// Пометить первую задачу выполненной
this.tasks[0].done = true
// Vue «увидит» изменение done
Однако если вы заменяете сам объект (например, через присваивание по индексу), в Vue 2 используйте $set или Vue.set!
Почему используются ключи :key в v-for
Ключи нужны Vue, чтобы давать каждому элементу «уникальную личность». Это важно, если переставляются, добавляются или удаляются элементы: Vue может быстро определить, какой DOM-элемент оставить, а какой — пересоздать. В качестве ключа подходит уникальный id из объекта массива (лучше не использовать индекс!).
Лучшие практики и подводные камни
Не используйте мутирующие методы, если не хотите изменить исходный массив
Методы filter, map, slice возвращают новые массивы, а sort, reverse, splice — мутируют исходный:
const newArr = this.tasks.map(task => ({...task})) // Возвращает новый массив объектов
this.tasks.sort((a, b) => a.text.localeCompare(b.text)) // Мутирует исходный список!
Если не хотите «сломать» данные, работайте с копией (например, перед сортировкой):
const sorted = [...this.tasks].sort(...)
Не мутируйте props
Если вы получили массив через prop, не изменяйте его напрямую внутри дочернего компонента. Создайте копию:
props: ['items'],
data() {
return {
localItems: this.items.slice() // Копия для локальной обработки
}
}
Работайте с массивами реактивно
В Vue 2 используйте $set и splice, в Vue 3 можно обновлять массивы напрямую и реактивность сохранится:
// Для Vue 2:
this.$set(this.tasks, index, newValue)
// Для Vue 3:
this.tasks[index] = newValue
Обработка массивов из асинхронных источников
Работа с API и обновление массива
Часто нужно загружать массивы данных из API:
mounted() {
fetch('https://jsonplaceholder.typicode.com/todos')
.then(res => res.json())
.then(tasks => {
this.tasks = tasks
})
}
- После присваивания this.tasks реактивность сохранится — список автоматически обновится.
Реактивное обновление после фильтра/поиска
Массивы, пришедшие из API, можно фильтровать вычисляемым свойством или в обработчике:
data() {
return {
tasks: [],
search: ''
}
},
computed: {
filteredTasks() {
return this.tasks.filter(task =>
task.text.toLowerCase().includes(this.search.toLowerCase())
)
}
}
Использование массивов с формами (v-model и v-for)
Частая задача — связывать элементы массива со входными данными:
<ul>
<li v-for="(task, idx) in tasks" :key="task.id">
<input v-model="task.text" />
<input type="checkbox" v-model="task.done" />
</li>
</ul>
- Любое изменение текста или чекбокса меняет соответствующее поле объекта (реактивно).
Если вы добавляете новый элемент:
this.tasks.push({ id: Date.now(), text: '', done: false })
Новый элемент сразу станет редактируемым и появится на экране.
Использование методов массивов в шаблоне
В шаблоне лучше не применять методы массивов (как filter или map) прямо внутри v-for. Это может привести к тому, что функция будет выполняться заново на каждый рендер, что плохо с точки зрения производительности. Используйте вычисляемые свойства:
computed: {
doneTasks() {
return this.tasks.filter(task => task.done)
}
}
И выводите:
<ul>
<li v-for="task in doneTasks" :key="task.id">{{ task.text }}</li>
</ul>
Использование массивов в сложных структурах данных
Часто массивы хранятся не на верхнем уровне, а «вложены» в объекты. Например, массив комментариев внутри задачи. Обновлять такие структуры нужно аккуратно:
// Добавить комментарий к задаче
const task = this.tasks.find(t => t.id === 1)
if (task) {
task.comments.push({ text: 'Новый комментарий', date: new Date() })
}
Если для обновления вложенного массива вы заменяете его целиком:
task.comments = updatedComments // в Vue 3 всё ок, в Vue 2 — используйте this.$set(task, 'comments', updatedComments)
Работа с массивами в Vuex
При использовании Vuex массивы хранятся в store. Все манипуляции с ними должны проходить через мутации:
// Внутри модуля Vuex
mutations: {
addTask(state, newTask) {
state.tasks.push(newTask)
},
removeTask(state, id) {
state.tasks = state.tasks.filter(task => task.id !== id)
}
}
В компонентах используйте dispatch для вызова действий и commit для мутаций:
this.$store.commit('addTask', { id: 4, text: 'Ещё одна задача', done: false })
Итоги
Массивы — одна из важнейших структур данных для приложений на Vue. От того, насколько правильно вы с ними работаете, зависит скорость, надежность и удобство поддержки вашего интерфейса. В большинстве случаев работа с массивами интуитивно похожа на стандартную JavaScript-практику, но есть нюансы, связанные с реактивностью и принципами одностороннего потока данных во Vue.
Вот основные моменты, которые важно запомнить:
- Для отображения массива используйте v-for и указывайте уникальный ключ.
- Работайте с массивами через методы, которые поддерживают реактивность (splice, push, $set).
- В Vue 2 есть ограничения по прямой работе с массивами, а в Vue 3 они решены.
- Используйте вычисляемые свойства для фильтрации и сортировки.
- Для данных из props или API всегда делайте копию, прежде чем их мутировать.
- Не вызывайте тяжелые методы массива прямо в шаблоне (в v-for), используйте computed.
Такой подход позволяет вам строить масштабируемые, быстрые и надежные интерфейсы во Vue, где любые изменения в массиве моментально отражаются в представлении.
Частозадаваемые технические вопросы по теме статьи и ответы на них
Как оптимально обновлять большой список данных, чтобы не вызвать лагов интерфейса?
Используйте виртуализацию: встроенные плагины вроде vue-virtual-scroller помогут отображать только видимые элементы списка во viewport. Это снизит нагрузку на DOM при рендере больших массивов.
Как изменить порядок элементов в массиве и чтобы интерфейс обновился?
Перемешайте массив через методы JavaScript (например, sort или splice). Внимательно следите за ключами в v-for — если у элементов ключ совпадает после перестановки, DOM не перестроится корректно. Поэтому всегда используйте уникальные ключи и сортируйте массив на уровне данных, а не шаблона.
Почему мой массив не обновляется в Vuex после асинхронного запроса?
Все изменения состояния должны быть через мутации. После получения данных из API вызывайте commit, чтобы записать их в массив, и только после этого интерфейс обновится.
Как отслеживать изменения внутри объектов массива, если они глубоко вложены?
Используйте Vue.set (или this.$set) для обновления новых полей в вложенных объектах массива. Для глубоких структур можно использовать глубокие watch-еры с опцией deep true, но следите за производительностью.
Могу ли я напрямую присваивать новый массив задач из итерации другого массива?
Да, но делайте это через копирование значений (например, tasks = oldTasks.map(task => { ...task })) чтобы не потерять реактивность, особенно если старый массив был связан с prop или store. В случае Vue 2 избегайте прямого изменения props — сначала скопируйте массив в локальное состояние компонента.
Постройте личный план изучения Vue до уровня Middle — бесплатно!
Vue — часть карты развития Frontend
100+ шагов развития
30 бесплатных лекций
300 бонусных рублей на счет
Бесплатные лекции
Все гайды по Vue
Лучшие курсы по теме

Vue 3 и Pinia
Антон Ларичев
TypeScript с нуля
Антон Ларичев