Увійти Реєстрація
Блог Серії
Кар'єра
Вакансії Компанії
Навчання
Документація Співбесіди Тестування Відео
Екосистема
Пакети Ресурси Проєкти Інструменти Події
Інше
Про нас Реклама

Чому реактивний об'єкт не дорівнює оригіналу і що таке toRaw та markRaw?

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 радить тримати стабільну межу: або завжди проксі, або завжди сирий.

Докладніше в документації: toRaw і markRaw

Перевір себе

20 випадкових питань за спробу, після завершення - розбір кожної помилки

Схожі питання