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

Управление переменными и реактивными свойствами во Vue

Автор

Олег Марков

Введение

Когда вы работаете с современными фронтенд-фреймворками, становится очевидно — "реактивность" играет одну из ключевых ролей в построении интерфейсов. Vue — не исключение. Возможность легко управлять переменными, чтобы ваш UI мгновенно реагировал на любые изменения данных, — залог удобных и отзывчивых приложений.

В этой статье мы подробно разберём подходы к управлению переменными и реактивными свойствами в Vue, а также самые важные инструменты — такие как ref, reactive, методы наблюдения и computed-поля. Я покажу вам распространённые способы объявления переменных, особенности их использования, а также объясню, как правильно реагировать на изменения данных. Всё это на простых и понятных примерах, чтобы вы могли сразу применять полученные знания на практике.

Основы реактивности во Vue

Что такое реактивность в Vue

Vue позволяет создавать переменные и объекты, которые автоматически отслеживают все изменения. Так, когда вы обновляете значение, все связанные части интерфейса моментально получают новые данные — ручная перерисовка или вызовы обновлений не нужны.

В основе Vue лежит реактивная система, основанная на прокси (Proxy). Это значит, что объект "наблюдается" и любые изменения — будь то обновление значения, добавление или удаление поля — могут быть обнаружены и обработаны.

Различие между обычными переменными и реактивными

Если вы объявите переменную обычным способом (к примеру, через let), Vue не будет её отслеживать:

let count = 0
count++ // Интерфейс не обновится, потому что нет реактивности

Если же использовать специальные методы, такие как ref или reactive, изменения будут замечены Vue:

import { ref } from 'vue'

const count = ref(0)
count.value++ // Интерфейс обновится, если count используется в шаблоне

Как видите, небольшое отличие в объявлении полностью меняет подход к работе с данными.

Использование ref: реактивные примитивы и ссылки

Объявление и работа с ref

Функция ref — основной способ создать реактивную переменную, которая будет хранить примитив (число, строку, булево значение) или ссылку на объект. Например:

import { ref } from 'vue'

const message = ref('Привет, Vue!') // Создаём реактивную строку

Как работает value

Обратите внимание, что для доступа к значению используется .value:

console.log(message.value) // Выведет 'Привет, Vue!'
message.value = 'Новое сообщение'

Это обязательное требование, так как ref на самом деле возвращает объект-обёртку.

Пример в компоненте

Смотрите, я покажу вам, как это выглядит в компоненте Vue 3 с Composition API:

<template>
  <div>
    <input v-model="userInput" />
    <p>Вы ввели: {{ userInput }}</p>
    <button @click="userInput = ''">Очистить</button>
  </div>
</template>

<script setup>
import { ref } from 'vue'

const userInput = ref('')
</script>

Пояснения:

  • userInput — реактивная переменная.
  • Двусторонее связывание v-model работает с .value автоматически.
  • Кнопка очищает содержимое переменной — интерфейс обновляется сразу.

Когда стоит использовать ref

Используйте ref, когда вам нужно создать переменную для хранения числа, строки, булевого значения или ссылки на объект, и хотите отслеживать её изменения в шаблоне либо в коде.

Использование reactive: реактивные объекты

Объявление и работа

Метод reactive позволяет получить полноценный реактивный объект. Почти всё, что вы делаете с таким объектом, будет отслеживаться Vue:

import { reactive } from 'vue'

const state = reactive({
  counter: 0,
  user: {
    name: 'Анна',
    age: 27
  }
})

Теперь любые изменения внутри state автоматически отразятся в интерфейсе.

Пример работы

Давайте перейдём к реальному примеру с формой:

<template>
  <div>
    <input v-model="form.username" placeholder="Имя" />
    <input v-model.number="form.age" placeholder="Возраст" />
    <p>Пользователь: {{ form.username }}, возраст: {{ form.age }}</p>
    <button @click="resetForm">Сброс</button>
  </div>
</template>

<script setup>
import { reactive } from 'vue'

const form = reactive({
  username: '',
  age: null
})

function resetForm() {
  form.username = ''
  form.age = null
}
</script>

Инструкция:

  • Форма хранит состояние в реактивном объекте form.
  • v-model автоматически работает с полями объекта.
  • При сбросе все поля формы возвращаются в начальное состояние — изменения сразу отражаются в шаблоне.

Глубокая реактивность

Vue отслеживает ВСЕ вложенные свойства реактивного объекта. Однако, если вы динамически добавляете новые поля, их реактивность может работать не сразу. Рекомендуется определять все необходимые поля заранее.

Когда использовать reactive

reactive отлично подойдёт для описания структуры состояния, хранящегося в виде объектов или массивов с несколькими значениями. Это удобно, если ваш компонент работает с формами, списками или сложными вложенными данными.

Массивы и их реактивность

Объявление реактивного массива

Вы можете создавать реактивные массивы теми же способами, что и объекты:

import { reactive } from 'vue'

// Массив реактивных задач
const tasks = reactive([
  { id: 1, text: 'Купить хлеб', done: false },
  { id: 2, text: 'Позволить код', done: true }
])

Особенности обновления массивов

Любое изменение массива через стандартные методы (push, pop, splice и др.) будет отслеживаться, и интерфейс автоматически обновится.

// Добавим задание
tasks.push({ id: 3, text: 'Прочитать статью', done: false })

// Переключим статус
tasks[0].done = true

о работе с массивами через ref

Массив можно также сделать реактивным через ref, если хотите использовать преимущество обёртки:

const numbers = ref([1, 2, 3])

// Обновление: только через .value
numbers.value.push(4)

computed — вычисляемые реактивные свойства

Общая суть

computed — это способ создавать значения, автоматически пересчитываемые при изменении зависимых переменных. Их главное отличие от методов — кеширование результата до тех пор, пока не изменятся зависимые данные.

Пример использования computed

import { reactive, computed } from 'vue'

const state = reactive({
  price: 100,
  quantity: 5
})

// Вычисляем итоговую сумму
const total = computed(() => state.price * state.quantity)

Использование в шаблоне

<template>
  <div>
    <input v-model.number="state.price" />
    <input v-model.number="state.quantity" />
    <p>Итог: {{ total }}</p>
  </div>
</template>

Дополнительные возможности

computed можно объявлять с геттером и сеттером:

const count = ref(0)

const doubleCount = computed({
  get: () => count.value * 2,
  set: val => { count.value = val / 2 }
})

Теперь можно не только получать, но и задавать новое значение doubleCount.

Когда использовать computed

Если вам необходимо производное значение, которое зависит от реактивных переменных — используйте computed. Например: фильтрация списка, форматирование вывода, подсчёты на лету.

watch — отслеживание изменений

Основное использование

С помощью функции watch можно выполнять действия в ответ на изменения одной или нескольких реактивных переменных.

import { ref, watch } from 'vue'

const name = ref('Андрей')

watch(name, (newVal, oldVal) => {
  // Сюда попадём при каждом изменении name
  console.log(`Имя изменилось с ${oldVal} на ${newVal}`)
})

Более сложные случаи

Можно реагировать на объекты, массивы или несколько переменных сразу:

watch([price, quantity], ([newPrice, newQuantity], [oldPrice, oldQuantity]) => {
  // Реакция на изменения любой из переменных
})

С опцией immediate

Если хотите выполнить watch сразу после создания, используйте опцию immediate:

watch(name, callback, { immediate: true })

Глубокое наблюдение за объектами

Если хотите следить за всеми вложенными изменениями, используйте опцию deep:

watch(
  () => state.user, // наблюдаем за объектом user
  (newUser) => { /* обработка */ },
  { deep: true }
)

Когда использовать watch

Используйте watch, если нужно выполнять побочные эффекты — например, запрос данных с сервера при изменении переменной, валидацию данных, отправку событий.

Синтаксис и место для переменных в Vue 2 и 3

Отличия между Vue 2 и Vue 3

Vue 2 использует data, methods, computed для объявления переменных и вычисляемых свойств:

export default {
  data() {
    return {
      count: 0
    }
  },
  computed: {
    doubleCount() {
      return this.count * 2
    }
  }
}

Vue 3 (Composition API) позволяет объявлять реактивные переменные через ref и reactive в <script setup> или обычном setup():

import { ref, computed } from 'vue'

const count = ref(0)
const doubleCount = computed(() => count.value * 2)

В шаблоне всё работает одинаково, разница только в синтаксисе JS части.

Лучшие практики работы с реактивностью

Каким способом объявлять переменные

  • Используйте ref для примитивов, отдельных переменных, ссылок на элементы, флагов.
  • Используйте reactive для объектов, массивов, структур состояния "в одном месте".
  • Не храните ссылку на реактивный объект в обычной переменной — Vue не сможет за ней следить.

Не смешивайте ref и reactive без необходимости

Бывает путаница, если реактивный объект содержит ref внутри себя или наоборот. Обычно выбирайте всегда один подход внутри одного блока данных.

Итерирование и изменение массивов

Добавляйте и удаляйте элементы только через Vue-механизмы (push, splice и прочие) — избегайте прямой перезаписи всего массива при необходимости сохранить реактивность.

Не забывайте про .value у ref

Внутри методов и скриптов всегда обращайтесь к .value у ref, если только работаете не со свойством в шаблоне.

Оптимизация вычислений

Если вычисляемое свойство не зависит ни от каких других реактивных переменных, нет нужды делать его компьютерным. Используйте простую функцию или метод.

Заключение

Реактивность во Vue — мощный фундамент, а грамотное управление переменными позволяет не только создавать современный UI, но и значительно упрощает поддержку проекта. Вы узнали, как использовать ref и reactive для разных типов данных, работали с массивами и объектами, а также научились отслеживать изменения через computed и watch. Осваивая эту базу, вы сможете строить действительно гибкие, динамичные и легко масштабируемые интерфейсы на Vue.

Частозадаваемые технические вопросы по теме и ответы

Почему не работает реактивность при добавлении нового свойства объекту через reactive?

Vue не может "увидеть" новые свойства, если вы добавили их после создания объекта. Определяйте все нужные поля заранее. Если нужно динамически добавить свойство — скопируйте объект в новый и добавьте свойство, тогда реактивность сохранится: js state = { ...state, newField: 'значение' }

Как сделать реактивным вложенный объект внутри ref?

ref не делает вложенные объекты глубоко реактивными по умолчанию. Если вы храните объект внутри ref, либо используйте reactive, либо вручную обёртывайте вложенность через reactive: js const obj = ref({ foo: 1 }) obj.value = reactive({ foo: 1 })

Можно ли использовать ref и reactive с TypeScript?

Да, оба инструмента поддерживают типизацию. Для ref — указывайте тип: js const myVar = ref<string>('начальное значение') Для reactive — задавайте тип целого объекта: js const state = reactive<{name: string, age: number}>({name: '', age: 0})

Когда стоит использовать watchEffect вместо watch?

watchEffect исполняет функцию немедленно и автоматически отслеживает все использованные реактивные зависимости. Он подходит, если вы не знаете заранее, что именно будете отслеживать: js import { watchEffect } from 'vue' watchEffect(() => { /* тело эффекта */ }) В противном случае используйте обычный watch.

Как получить доступ к реактивным переменным вне компонента?

Передавать такие переменные можно через provide/inject или создавать отдельные reactive-структуры (например, store на базе reactive/ref) и импортировать их там, где нужно.


Примечание: Для максимально плавной интеграции Vue всегда предпочитайте специализированные API (ref, reactive, computed, watch) для управления состоянием — это обеспечит корректную реакцию интерфейса и сократит количество багов.

Использование v for и slot в VueСтрелочка вправо

Все гайды по Vue

Работа с пользовательскими интерфейсами и UI библиотеками во VueОрганизация и структура исходных файлов в проектах VueОбзор популярных шаблонов и стартовых проектов на VueКак организовать страницы и маршруты в проекте на VueСоздание серверных приложений на Vue с помощью Nuxt jsРабота со стилями и CSS в Vue js для красивых интерфейсовСоздание и структурирование Vue.js приложенияНастройка и сборка проектов Vue с использованием современных инструментов
Управление переменными и реактивными свойствами во VueИспользование v for и slot в VueТипизация и использование TypeScript в VuejsИспользование шаблонов в Vue js для построения интерфейсовПередача данных между компонентами с помощью props в Vue jsУправление property и функциями во Vue.jsОсновы работы с объектами в VueПонимание жизненного цикла компонента Vue js на примере mountedИспользование метода map в Vue для обработки массивовОбработка пользовательского ввода в Vue.jsОрганизация файлов и структура проекта Vue.jsКомпоненты Vue создание передача данных события и emitИспользование директив и их особенности на Vue с помощью defineСоздание и использование компонентов в Vue JSОбработка кликов и пользовательских событий в Vue
Открыть базу знаний