ref и reactive: два способа хранить состояние
Разбираем главную развилку реактивности Vue 3 — ref против reactive: как они устроены, зачем ref нужен .value и какой брать в каком случае.
ref делает реактивным любое значение (число, строку, объект), оборачивая его в объект со свойством
.value. reactive делает реактивным сам объект целиком, без обёртки.
ref: обёртка над значением
ref подходит для одиночных значений: числа, строки, булевы. Чтобы примитив можно было отслеживать, Vue кладёт его внутрь объекта-обёртки. Реальное значение — в .value:
// Имитируем, как устроен ref: значение лежит в .value
function ref(initial) {
return { value: initial };
}
const count = ref(0);
console.log("Сейчас:", count.value);
count.value = count.value + 1;
console.log("После +1:", count.value);
Вывод:
Сейчас: 0 После +1: 1
Это и есть причина, по которой в скрипте пишут count.value. В шаблоне же Vue разворачивает ref сам — там пишут просто {{ count }}.
reactive: реактивный объект
reactive работает с объектами и массивами. Он возвращает реактивный прокси — свойства читаются и пишутся напрямую, без .value:
<template>
<p>{{ user.name }}, возраст {{ user.age }}</p>
<button @click="user.age++">Старше</button>
</template>
<script setup>
import { reactive } from 'vue'
const user = reactive({ name: 'Аня', age: 25 })
</script>
Когда что выбирать
| Случай | Брать |
| Примитив (число, строка, булево) | ref |
| Объект или массив | ref или reactive |
| Нужна единая запись для всего | ref везде |
Распространённая рекомендация сообщества: используйте ref по умолчанию для всего. Тогда правило простое — «в скрипте всегда .value». Это избавляет от путаницы «здесь с .value, а здесь без». ref с объектом внутри тоже полностью реактивен (Vue применяет reactive к его содержимому автоматически).
ref с объектом
function ref(initial) { return { value: initial }; }
// ref может хранить и объект — тогда меняем через .value
const state = ref({ items: [], total: 0 });
state.value.items.push("молоко");
state.value.total = state.value.items.length;
console.log(state.value);
Вывод:
{ items: [ 'молоко' ], total: 1 }
Главное про различие
ref— универсален, но в скрипте требует.value.reactive— только для объектов/массивов, без.value, но с подвохами (о них — следующий урок).
Итог
ref(v)оборачивает значение; в скрипте —.value, в шаблоне — без него.reactive(obj)делает реактивным объект целиком, доступ к свойствам напрямую.- Практичный выбор по умолчанию —
refвезде: единое правило «.valueв скрипте». refс объектом внутри тоже полностью реактивен.