Запропонувати правкуПокращити цю статтюДопрацюйте відповідь до «Як Vue відстежує зміни даних?». Ваші зміни проходять модерацію перед публікацією.Потрібне підтвердженняКонтентЩо ви змінюєте🇺🇸EN🇺🇦UAПереглядЗаголовок (UA)Коротка відповідь (UA)**Реактивна система Vue** відстежує зміни даних через Proxy (у Vue 3) або Object.defineProperty() (у Vue 2), перехоплюючи читання і запис властивостей об'єкта. **Ключове:** коли дані читаються, Vue реєструє залежність, а коли змінюються - сповіщає залежні ефекти.Показується над повною відповіддю для швидкого нагадування.Відповідь (UA)Зображення## Як Vue відстежує зміни даних Vue реалізує **реактивну систему на основі Proxy** (у Vue 3) або `Object.defineProperty()` (у Vue 2). Основна ідея - **перехоплення доступу до властивостей об'єктів** (читання і запис), щоб знати: - коли дані **читаються** -> зареєструвати залежність - коли дані **змінюються** -> сповістити залежні ефекти (компоненти, обчислювані властивості, watch тощо) --- ## Механізм на рівні Proxy (Vue 3) Коли ви створюєте реактивний об'єкт через `reactive()` або `ref()`, Vue огортає його за допомогою `Proxy`. ### Приклад: ```javascript import { reactive, effect } from 'vue' const state = reactive({ count: 0 }) effect(() => { console.log(`Count: ${state.count}`) }) state.count++ // тригерить effect -> виводить "Count: 1" ``` ### Що відбувається крок за кроком: 1. **Створення Proxy** ```javascript const proxy = new Proxy(target, { get(target, key, receiver) { track(target, key) // реєструє залежність return Reflect.get(target, key, receiver) }, set(target, key, value, receiver) { const result = Reflect.set(target, key, value, receiver) trigger(target, key) // повідомляє підписників про зміну return result } }) ``` 2. **Функція** `track()` - Викликається при читанні властивості (`get`). - Реєструє, що поточне обчислення (наприклад, рендер компонента) залежить від цієї властивості. - Vue зберігає залежності у **WeakMap -> Map -> Set**: ```javascript targetMap = WeakMap { target (об'єкт) -> Map { key (поле) -> Set(effect) } } ``` 3. **Функція** `trigger()` - Викликається при записі (`set`). - Знаходить усі ефекти (наприклад, функції рендера), які залежать від зміненого ключа. - Викликає їх повторно -> інтерфейс оновлюється. --- ## Механізм у Vue 2 (`Object.defineProperty`) У старій версії Vue не було `Proxy`, тому Vue **перевизначав геттери і сеттери** кожної властивості вручну: ```javascript Object.defineProperty(obj, 'count', { get() { Dep.depend() // підписуємо спостерігачів return value }, set(newVal) { value = newVal Dep.notify() // повідомляємо всіх спостерігачів } }) ``` Але цей підхід мав обмеження: - не можна було відстежувати додавання нових властивостей (`obj.newProp = ...`) - не можна було відстежувати видалення властивостей - доводилося використовувати `Vue.set()` і `Vue.delete()` Тому у Vue 3 перейшли на **Proxy**, який вирішує всі ці проблеми. --- ## Підсумок | Версія Vue | Механізм реактивності | Що перехоплює | Обмеження | |---|---|---|---| | Vue 2 | `Object.defineProperty()` | Тільки наявні властивості | Не бачить нові ключі, потребує Vue.set() | | Vue 3 | `Proxy` | Будь-які операції читання/запису, включно з новими властивостями | Немає обмежень, швидше і чистіше |Для рев’юераПримітка для модератора (необов’язково)Бачить лише модератор. Прискорює рев’ю.