Функция reactive
reactive — второй способ объявить состояние. Он делает реактивным сам объект, поэтому к его полям обращаются напрямую, без .value. Подходит для группы связанных значений, например настроек фильтра.
Объявление
<!-- src/App.vue -->
<script setup>
import { reactive } from 'vue'
const filter = reactive({
query: '',
onlyActive: false,
})
function toggle() {
filter.onlyActive = !filter.onlyActive
}
</script>
<template>
<button @click="toggle">
{{ filter.onlyActive ? 'Показать все' : 'Только активные' }}
</button>
</template>Каждый клик меняет надпись на кнопке. Поле filter.onlyActive меняется в скрипте без .value, и Vue всё равно перерисовывает шаблон.
Ограничения
reactive работает только с объектами, массивами, Map и Set. Строку или число передать нельзя — для них есть только ref.
Второе ограничение важнее: реактивность теряется, если заменить объект целиком или разобрать его деструктуризацией.
<script setup>
import { reactive } from 'vue'
let filter = reactive({ query: '', onlyActive: false })
// Связь потеряна: шаблон по-прежнему видит старый объект
filter = reactive({ query: 'хлеб', onlyActive: true })
// query — обычная строка, её изменения Vue не увидит
const { query } = filter
</script>Деструктуризация из урока учебника про объекты здесь копирует значения в обычные переменные, и они перестают быть реактивными.
Сравнение
ref | reactive | |
|---|---|---|
| Типы | Любые | Только объекты и коллекции |
| Доступ в скрипте | count.value | filter.query |
| Замена целиком | todos.value = [] | Нельзя |
| Деструктуризация | Не нужна | Ломает реактивность |
Что выбрать
Документация Vue советует использовать ref по умолчанию: он работает с любыми значениями, его можно целиком заменить, например, данными из API, и по .value в коде сразу видно, где реактивная переменная. В курсе дальше используется ref. reactive удобен для небольших объектов-групп вроде формы, которые не заменяются целиком.
<script setup>
import { ref } from 'vue'
const filter = ref({ query: '', onlyActive: false })
function reset() {
filter.value = { query: '', onlyActive: false }
}
</script>С ref сброс к начальным значениям — одно присваивание.
Частая ошибка
Загрузить данные и присвоить их переменной reactive:
<script setup>
import { reactive } from 'vue'
let todos = reactive([])
async function load() {
const response = await fetch('/todos.json')
todos = await response.json() // Список на странице не обновится
}
</script>Объявите список через ref([]) и пишите todos.value = await response.json() — тогда новая ссылка на массив будет замечена.