Основы реактивности Vue
▸Что такое реактивность
Реактивность — это автоматическое обновление DOM при изменении данных. Vue 3 использует Proxy для отслеживания изменений.
ref: реактивные ссылки
▸Определение
1import { ref } from 'vue';23const count = ref(0);4console.log(count.value); // 05count.value++;
▸В template
1<template>2 <p>{{ count }}</p>3 <!-- автоматически распаковывается -->4</template>56<script setup>7import { ref } from 'vue';8const count = ref(0);9</script>
▸Для примитивов и объектов
1const name = ref('Иван'); // примитив2const user = ref({ name: 'Иван', age: 25 }); // объект34// Доступ к свойствам объекта5user.value.name = 'Николай'; // реактивно
reactive: реактивные объекты
▸Определение
1import { reactive } from 'vue';23const state = reactive({4 count: 0,5 user: { name: 'Иван' },6});78state.count++; // реактивно9state.user.name = 'Николай'; // реактивно
▸Ограничения
1let state = reactive({ count: 0 });2state = reactive({ count: 1 }); // потеря реактивности!
Разница между ref и reactive
▸Когда использовать ref
▸Когда использовать reactive
▸Проблемы reactive с деструктуризацией
1const state = reactive({ count: 0, name: 'Иван' });23// Теряется реактивность!4const { count, name } = state;56// Правильно — через toRefs7import { toRefs } from 'vue';8const { count, name } = toRefs(state);
computed: вычисляемые свойства
▸Определение
1import { ref, computed } from 'vue';23const firstName = ref('Иван');4const lastName = ref('Петров');56const fullName = computed(() => `${firstName.value} ${lastName.value}`);
▸Computed с getter и setter
1const fullName = computed({2 get: () => `${firstName.value} ${lastName.value}`,3 set: (newValue) => {4 const [first, last] = newValue.split(' ');5 firstName.value = first;6 lastName.value = last;7 },8});
▸Computed vs метод
1<template>2 <!-- Computed: кэшируется, пересчитывается только при изменении зависимостей -->3 <p>{{ fullName }}</p>45 <!-- Метод: выполняется при каждом ре-рендере -->6 <p>{{ getFullName() }}</p>7</template>
watch и watchEffect
▸watch
1import { ref, watch } from 'vue';23const count = ref(0);45watch(count, (newValue, oldValue) => {6 console.log(`Было: ${oldValue}, Стало: ${newValue}`);7});
▸watchEffect
1import { ref, watchEffect } from 'vue';23const count = ref(0);45watchEffect(() => {6 console.log(`Текущее значение: ${count.value}`);7 // Автоматически отслеживает зависимости8});
▸watch с объектом
1const user = ref({ name: 'Иван', age: 25 });23watch(4 () => user.value.name,5 (newName) => {6 console.log(`Имя изменилось на: ${newName}`);7 }8);910// Глубокое отслеживание11watch(user, (newUser) => {12 console.log('Пользователь изменился:', newUser);13}, { deep: true });
readonly: защита от изменений
1import { reactive, readonly } from 'vue';23const state = reactive({ count: 0 });4const readonlyState = readonly(state);56readonlyState.count++; // Ошибка! Изменение запрещено
shallowRef и shallowReactive
▸shallowRef
1import { shallowRef } from 'vue';23const user = shallowRef({ name: 'Иван' });4user.value.name = 'Николай'; // не реактивно!5user.value = { name: 'Николай' }; // реактивно
▸Когда использовать
toRef и toRefs
▸toRef
1const props = defineProps({ name: String });2const nameRef = toRef(props, 'name');
▸toRefs
1const state = reactive({ count: 0, name: 'Иван' });2const { count, name } = toRefs(state);34// Теперь count и name — реактивные ссылки5count.value++;
Заключение
Vue 3 предоставляет гибкую систему реактивности. ref — для примитивов и переприсвоения, reactive — для объектов, computed — для вычислений, watch — для побочных эффектов. Понимание этих инструментов — ключ к эффективной Vue-разработке.