reactive() повертає проксі над оригінальним об'єктом, а не сам об'єкт:
const raw = { a: 1 };
const state = reactive(raw);
state === raw; // false
toRaw(state) === raw; // true
reactive(raw) === state; // true - для одного оригіналу Vue повертає той самий проксі
Зміни через проксі змінюють оригінал (і запускають оновлення), а зміни оригіналу напряму - не запускають нічого.
Де це вилазить:
- порівняння й пошук:
items.value.indexOf(obj)чиSet.has(obj)з оригінальним об'єктом, коли в масиві лежать проксі (або навпаки), дають «не знайдено». Vue перехоплюєindexOf/includesу реактивних масивах, щоб пошук сирого об'єкта працював, але вMap,Setі власному коді порівняння за посиланням легко помилитися; - передача в сторонні бібліотеки: бібліотека отримує проксі. Бібліотеки, що порівнюють об'єкти за посиланням, змінюють їх інтенсивно чи покладаються на приватні поля (
#field), можуть працювати неправильно або повільно; - класи з приватними полями: метод, викликаний через проксі, отримує
this= проксі, а в проксі немає#field-TypeError; structuredClone(state)падає на проксі - потрібноstructuredClone(toRaw(state)).
toRaw(proxy) - отримати оригінал. Корисно для:
- передачі даних у сторонні бібліотеки,
postMessage,IndexedDB,structuredClone; - тимчасового читання/запису без відстеження й оновлень (масові зміни, після яких одне оновлення).
markRaw(obj) - позначити об'єкт як ніколи не реактивний: Vue не обгортатиме його в проксі навіть усередині реактивного стану.
const map = markRaw(new mapboxgl.Map({ container: 'map' }));
state.map = map; // лишається звичайним об'єктом
Застосовують для екземплярів сторонніх бібліотек (карти, редактори, графіки), складних класів, великих незмінних структур.
shallowRef / shallowReactive - реактивність лише на верхньому рівні: заміна значення відстежується, зміни всередині - ні. Добре для великих даних, що замінюються цілком.
Застереження: toRaw і markRaw - інструменти для конкретних проблем. Змішування сирих і реактивних версій того самого об'єкта в коді - джерело помилок «чому не оновилося». Документація Vue радить тримати стабільну межу: або завжди проксі, або завжди сирий.