Vue.js предоставляет мощный механизм реактивности, основанный на отслеживании изменений данных. Основное различие заключается между поверхностным (shallow) и глубоким (deep) отслеживанием, что существенно влияет на поведение реактивных свойств и вычисляемых эффектов.
Поверхностное отслеживание применяется по умолчанию при создании
реактивных объектов с помощью reactive() или
ref(). В этом случае Vue отслеживает только
изменения на первом уровне свойств объекта.
Пример:
import { reactive, effect } from 'vue';
const state = reactive({
user: {
name: 'Alice',
age: 25
}
});
effect(() => {
console.log(state.user.name);
});
state.user.name = 'Bob'; // Вызывает эффект
state.user.age = 26; // Эффект не сработает
Ключевой момент: изменение вложенных свойств объекта не всегда будет отслеживаться, если эти свойства не были реактивными при создании объекта.
Глубокое отслеживание позволяет Vue реагировать на изменения
всех уровней вложенности объектов и массивов. В
стандартном API оно доступно через watch() с параметром
{ deep: true }.
Пример:
import { reactive, watch } from 'vue';
const state = reactive({
user: {
name: 'Alice',
age: 25
}
});
watch(
() => state.user,
(newValue, oldValue) => {
console.log('Пользователь изменился', newValue);
},
{ deep: true }
);
state.user.age = 26; // Срабатывает watch
Особенности глубокого отслеживания:
Vue 3 создает реактивность на основе Proxy, что
позволяет отслеживать доступ к свойствам и их изменения.
Поведение reactive и
ref:
reactive(object) — создает реактивный объект с
поверхностным отслеживанием на верхнем уровне и
рекурсивной реактивностью вложенных объектов.ref(value) — создаёт реактивную ссылку на значение.
Если значение является объектом, оно автоматически превращается в
реактивный через reactive при доступе к свойствам через
.value.Пример:
import { reactive, ref } from 'vue';
const count = ref(0); // простое число
const user = ref({ name: 'Alice', age: 25 }); // объект внутри ref
count.value++; // реактивное обновление
user.value.name = 'Bob'; // также отслеживается благодаря реактивности объекта внутри ref
watch и effect используют реактивность
по-разному:
effect отслеживает любые зависимости,
используемые внутри функции, и срабатывает при их
изменении.watch позволяет задавать целевое
свойство и дополнительные параметры: immediate,
deep, flush.Пример различий:
import { reactive, effect, watch } from 'vue';
const state = reactive({ user: { name: 'Alice', age: 25 } });
effect(() => {
console.log(state.user.name); // только имя
});
watch(
() => state.user,
(newValue) => console.log(newValue),
{ deep: true } // все вложенные изменения
);
Вывод: effect удобен для быстрых
вычислений при использовании свойств, а watch нужен для
наблюдения и побочных эффектов.
Важно помнить, что глубокое копирование не сохраняет
реактивность по умолчанию. Использование
JSON.parse(JSON.stringify(obj)) создаёт обычный объект без
реактивности. Для сохранения реактивности следует использовать
reactive() или ref() для новых объектов.
import { reactive } from 'vue';
const original = reactive({ user: { name: 'Alice' } });
const copy = reactive(JSON.parse(JSON.stringify(original)));
copy.user.name = 'Bob'; // Не влияет на original и остаётся реактивным только в copy
ref для примитивов и объектов, когда нужно
контролировать реактивность вручную.Глубокое и поверхностное отслеживание — ключевые аспекты реактивности Vue, определяющие, какие изменения данных приводят к обновлению интерфейса. Понимание этих механизмов позволяет эффективно управлять состоянием приложений и оптимизировать производительность.