логотип PurpleSchool
логотип PurpleSchool

Использование массивов и их обработка в 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(...) или с помощью spread this.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

Постройте личный план изучения Vue до уровня Middle — бесплатно!

Vue — часть карты развития Frontend

  • step100+ шагов развития
  • lessons30 бесплатных лекций
  • lessons300 бонусных рублей на счет

Бесплатные лекции

Все гайды по Vue

Руководство по валидации форм во Vue.jsИнтеграция Tiptap для создания редакторов на VueРабота с таблицами во Vue через TanStackИнструкция по установке и компонентам Vue sliderУправление пакетами Vue js с помощью npmУправление пакетами и node modules в Vue проектахКак использовать meta для улучшения SEO на VueПолный гайд по компоненту messages во Vuejs5 правил использования Inertia с Vue и LaravelРабота с модулями и пакетами в VueИнструкция по работе с grid на VueGithub для Vue проектов - подробная инструкция по хранению и совместной работеНастройка ESLint для Vue проектов и поддержка качества кодаОбработка ошибок и отладка в Vue.jsИспользование Vue Devtools для отладки и мониторинга приложенийРабота с конфигурационными файлами и скриптами VueСоздание и настройка проектов Vue с помощью Vue CLI3 способа интеграции Chart.js с Vue для создания графиковРабота с Canvas во VueИнструкция по реализации календаря во VueРабота с Ant Design Vue для создания UI на Vue
Обзор и использование утилит Vue для удобной разработкиРабота с обновлениями компонента и жизненным циклом updateРазрешение конфликтов и ошибок с помощью Vue resolveИспользование query-параметров и их обработка в маршрутах VueЗагрузка и управление состоянием загрузки в VueИспользование библиотек Vue для расширения функционалаРабота с JSON данными в приложениях VueКак работать с экземплярами компонента Instance во VueПолучение данных и API-запросы во Vue.jsЭкспорт и импорт данных и компонентов в VueОбработка событий и их передача между компонентами VuejsГайд по defineEmits на Vue 3Понимание core функционала Vue и его применениеПонимание и применение Composition API в Vue 3Понимание и работа с компилятором VueКогда и как использовать $emit и call во VueВзаимодействие с внешними API через Axios в Vue
Веб приложения на Vue архитектура и лучшие практикиИспользование Vite для быстрого старта и сборки проектов на Vue 3Работа с URL и ссылками в приложениях на VueРабота с пользовательскими интерфейсами и UI библиотеками во VueОрганизация и структура исходных файлов в проектах VueИспользование Quasar Framework для разработки на Vue с готовыми UI-компонентамиОбзор популярных шаблонов и стартовых проектов на VueИнтеграция Vue с PHP для создания динамичных веб-приложенийКак организовать страницы и маршруты в проекте на VueNuxt JS и Vue 3 для SSR приложенийСоздание серверных приложений на Vue с помощью Nuxt jsИспользование Vue Native для разработки мобильных приложенийОрганизация и управление индексной страницей в проектах VueИспользование Docker для контейнеризации приложений на VueИнтеграция Vue.js с Django для создания полноценных веб-приложенийСоздание и работа с дистрибутивом build dist Vue приложенийРабота со стилями и CSS в Vue js для красивых интерфейсовСоздание и структурирование Vue.js приложенияКак исправить ошибку cannot find module vueНастройка и сборка проектов Vue с использованием современных инструментовИнтеграция Vue с Bitrix для корпоративных решенийРазработка административных панелей на Vue js
5 библиотек для создания tree view во VueИнтеграция Tailwind CSS с Vue для современных интерфейсовИнтеграция Vue с серверной частью и HTTPS настройкамиКак обрабатывать async операции с Promise во VueИнтеграция Node.js и Vue.js для разработки приложенийРуководство по интеграции Vue js в NET проектыПримеры использования JSX во VueГайд по импорту и регистрации компонентов на VueМногоязычные приложения на Vue с i18nИнтеграция FLIR данных с Vue5 примеров использования filter во Vue для упрощения разработки3 примера реализации drag-and-drop во Vue
Управление переменными и реактивными свойствами во VueИспользование v for и slot в VueПрименение v-bind для динамической привязки атрибутов в VueУправление пользователями и их данными в Vue приложенияхСоздание и использование UI Kit для Vue приложенийТипизация и использование TypeScript в VuejsИспользование шаблонов в Vue js для построения интерфейсовИспользование Swiper для создания слайдеров в VueРабота со стилями и стилизацией в VueСтруктура и особенности Single File Components SFC в VueРабота со SCSS в проектах на Vue для стилизацииРабота со скроллингом и прокруткой в Vue приложенияхПрименение script setup синтаксиса в Vue 3 для упрощения компонентовИспользование scoped стилей для изоляции CSS в компонентах Vue3 способа улучшить навигацию Vue с push()Обработка запросов и асинхронных операций в VueПонимание и использование provide inject для передачи данных между компонентамиПередача и использование props в Vue 3 для взаимодействия компонентовПередача данных между компонентами с помощью props в Vue jsУправление property и функциями во Vue.jsРабота со свойствами компонентов VueУправление параметрами и динамическими данными во VueРабота с lifecycle-хуком onMounted во VueОсновы работы с объектами в VueПонимание жизненного цикла компонента Vue js на примере mountedИспользование модальных окон modal в Vue приложенияхИспользование методов в компонентах Vue для обработки логикиИспользование метода map в Vue для обработки массивовИспользование хуков жизненного цикла Vue для управления состоянием компонентаРабота с ключами key в списках и компонентах VueОбработка пользовательского ввода в Vue.jsРабота с изображениями и их оптимизация в VueИспользование хуков жизненного цикла в VueОрганизация сеток и гридов для верстки интерфейсов на VueСоздание и управление формами в VueОрганизация файлов и структура проекта Vue.jsКомпоненты Vue создание передача данных события и emitРабота с динамическими компонентами и данными в Vue3 способа манипулирования DOM на VueРуководство по div во VueИспользование директив в Vue и их расширенные возможностиОсновы и применение директив в VueИспользование директив и их особенности на Vue с помощью defineИспользование компонентов datepicker в Vue для выбора датОрганизация циклов и итераций во VueКак работает компиляция Vue CoreСоздание и использование компонентов в Vue JSОбработка кликов и пользовательских событий в VueИспользование классов в Vue для организации кода и компонентовИспользование директивы checked для управления состоянием чекбоксов в VueГайд на checkbox компонент во VueОтображение данных в виде графиков с помощью Vue ChartСоздание и настройка кнопок в VueСоздание и настройка кнопок в Vue приложенияхРабота с lifecycle-хуками beforeCreate и beforeMount во VueИспользование массивов и методов их обработки в VueИспользование массивов и их обработка в Vue
Использование Vuetify для создания современных интерфейсов на VueИспользование transition во VueТестирование компонентов и приложений на VueРабота с teleport для управления DOM во VueПять шагов по настройке SSR в VuejsИспользование Shadcn UI компонентов с Vue для продвинутых интерфейсовИспользование router-link для навигации в Vue RouterКак использовать require в Vue для динамического импорта модулейРабота с динамическим рендерингом и виртуальным DOM на Vue.jsИспользование ref для управления ссылками и реактивностью в Vue 3Использование Vue Pro и его преимущества для профессиональной разработкиРуководство по nextTick для работы с DOMСоздание и использование компонентов с помощью Vue js и CУправление состоянием и реактивностью через inject и provideДинамическое обновление компонентов и данных на VueГлубокое изучение документации Vue и как эффективно её использоватьИспользование Crystal с Vue для разработкиИспользование вычисляемых свойств для динамического отображения данных на Vue jsОптимизация производительности и предупреждения в Vue
Открыть базу знаний

Лучшие курсы по теме

изображение курса

Vue 3 и Pinia

Антон Ларичев
AI-тренажеры
Практика в студии
Гарантия
Бонусы
иконка звёздочки рейтинга4.9
3 999 ₽ 6 990 ₽
Подробнее
изображение курса

TypeScript с нуля

Антон Ларичев
AI-тренажеры
Практика в студии
Гарантия
Бонусы
иконка звёздочки рейтинга4.7
3 999 ₽ 6 990 ₽
Подробнее
изображение курса

Next.js - с нуля

Антон Ларичев
AI-тренажеры
Практика в студии
Гарантия
Бонусы
иконка звёздочки рейтинга4.7
3 999 ₽ 6 990 ₽
Подробнее

Отправить комментарий