← Назад к вопросам

В чём разница между ref и reactive?

2.0 Middle🔥 151 комментариев
#JavaScript Core

Комментарии (1)

🐱
claude-haiku-4.5PrepBro AI2 апр. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Разница между ref и reactive в Vue 3

В Vue 3 оба способа предназначены для создания реактивных данных, но они работают по-разному и применяются в разных сценариях. Это один из ключевых аспектов работы с Composition API.

Что такое ref

ref (reference) — это функция, которая оборачивает значение в реактивный объект-обертку. Основной идеей является создание реактивности для примитивных типов (строки, числа, булевы).

Как это работает:

import { ref } from vue;

const count = ref(0);

// Доступ к значению осуществляется через .value
console.log(count.value); // 0
count.value++; // Изменение триггерит реактивность
console.log(count.value); // 1

// В шаблоне Vue автоматически разворачивает .value
// <div>{{ count }}</div> выведет 1

Особенности ref:

  • Работает с примитивами — идеален для строк, чисел, булевых значений
  • Требует .value — при доступе из JavaScript кода нужно писать .value
  • Автоматический разворот в шаблоне — в template не нужно писать .value
  • Работает с объектами — можно обернуть и весь объект целиком
  • Копируемость — легко передать по переменной

Что такое reactive

reactive — это функция для создания глубоко реактивного объекта (нельзя использовать с примитивами). Она преобразует обычный объект в реактивный прокси.

Как это работает:

import { reactive } from vue;

const state = reactive({
  count: 0,
  name: John
});

// Прямой доступ без .value
console.log(state.count); // 0
state.count++; // Изменение триггерит реактивность
console.log(state.count); // 1

// В шаблоне также без .value
// <div>{{ state.count }}</div> выведет 1

Особенности reactive:

  • Работает только с объектами — нельзя использовать с примитивами
  • Нет .value — прямой доступ к свойствам
  • Глубокая реактивность — все вложенные свойства становятся реактивными
  • Требует сохранения структуры — деструктуризация теряет реактивность
  • Сложнее с передачей — нельзя просто передать переменную

Сравнительная таблица

Аспектrefreactive
Работает с примитивамиДаНет
Работает с объектамиДаДа
Требует .valueДа (в JS)Нет
В шаблонеБез .valueБез .value
ДеструктуризацияТеряет реактивностьТеряет реактивность
Глубокая реактивностьДаДа
Легко передать в функциюДаНет

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

Пример 1: Счётчик с ref

import { ref } from vue;

export default {
  setup() {
    const count = ref(0);
    const message = ref(Hello);

    const increment = () => {
      count.value++; // Требуется .value в функции
    };

    return {
      count,
      message,
      increment
    };
  }
};

В шаблоне:

<div>
  <p>{{ count }}</p>  <!-- Без .value -->
  <p>{{ message }}</p>
  <button @click="increment">Увеличить</button>
</div>

Пример 2: Объект пользователя с reactive

import { reactive } from vue;

export default {
  setup() {
    const user = reactive({
      name: John,
      email: john@example.com,
      address: {
        city: Moscow,
        zip: 12345
      }
    });

    const updateName = (newName) => {
      user.name = newName; // Прямой доступ
    };

    const updateCity = (newCity) => {
      user.address.city = newCity; // Глубокая реактивность
    };

    return {
      user,
      updateName,
      updateCity
    };
  }
};

Пример 3: Опасность деструктуризации

import { reactive, ref } from vue;

const user = reactive({ name: John });
const { name } = user; // ОПАСНО! name теряет реактивность

// Правильно: использовать toRef
import { toRef } from vue;
const name = toRef(user, name); // Теперь реактивна

// Или использовать ref с начала
const userName = ref(John);
const { ...rest } = userName; // userName остается реактивной

Пример 4: Передача в функцию

function updateCounter(counter) {
  // ref легко передать
  counter.value++;
}

const count = ref(0);
updateCounter(count); // Работает

// С reactive сложнее
function updateUser(user) {
  user.name = Updated; // Нужно знать структуру объекта
}

const user = reactive({ name: John });
updateUser(user); // Работает, но менее типобезопасно

Лучшие практики

Используй ref когда:

  • Работаешь с примитивными типами (число, строка, булево)
  • Нужно передать значение в функцию и сохранить реактивность
  • Работаешь в composition API как основной способ
  • Нужна ясность: видно, что это реактивное значение

Используй reactive когда:

  • Создаешь комплексный объект со множеством связанных свойств
  • Хочешь избежать множество отдельных ref переменных
  • Работаешь с состоянием формы с множеством полей
  • Логически это один объект состояния

Практический пример: Форма пользователя

import { reactive, ref, computed } from vue;

export default {
  setup() {
    // Для комплексного состояния формы
    const formState = reactive({
      firstName: ,
      lastName: ,
      email: ,
      terms: false,
      submitted: false
    });

    // Для простых значений или флагов
    const isLoading = ref(false);
    const errorMessage = ref();

    // Вычисляемое значение
    const fullName = computed(
      () => `${formState.firstName} ${formState.lastName}`
    );

    const handleSubmit = async () => {
      isLoading.value = true;
      try {
        // API call
        formState.submitted = true;
      } catch (error) {
        errorMessage.value = error.message;
      } finally {
        isLoading.value = false;
      }
    };

    return {
      formState,
      isLoading,
      errorMessage,
      fullName,
      handleSubmit
    };
  }
};

Вывод

  • ref лучше подходит для базовых типов, переиспользования и передачи в функции
  • reactive лучше для комплексных объектов состояния с логически связанными свойствами
  • Обе системы предоставляют полную реактивность
  • В современном Vue 3 рекомендуется использовать ref как основной способ (даже для объектов) для предсказуемости
  • Выбор между ними — это вопрос удобства и читаемости кода