Skip to main content

Proxy і нова система реактивності

1. Проблема: неможливість відстежувати нові властивості

У Vue 2

Реактивність створювалася за допомогою Object.defineProperty(). Вона "обгортала" лише наявні поля на момент ініціалізації.

javascript
data() { return { user: { name: 'Tim' } } } this.user.age = 30 // не реактивно! Vue.set(this.user, 'age', 30) // потрібно вручну

У Vue 3

Proxy перехоплює всі операції get, set, delete, тому Vue автоматично відстежує нові поля:

javascript
const user = reactive({ name: 'Tim' }) user.age = 30 // реактивно! delete user.name // теж реактивно!

Вирішена проблема: можна додавати/видаляти властивості динамічно, без Vue.set().


2. Проблема: слабка робота з масивами

У Vue 2

Масиви не були повністю реактивними:

  • Зміна за індексом не відстежувалася:

    javascript
    this.items[2] = 'new' // не спрацює
  • Доводилося використовувати Vue.set(this.items, 2, 'new').

  • Vue "патчив" (override) методи масивів (push, pop, splice), що було громіздко і знижувало продуктивність.

У Vue 3

Proxy перехоплює всі операції з масивами, зокрема індекси і довжину.

javascript
const arr = reactive(['a', 'b']) arr[1] = 'x' // реактивно arr.push('c') // реактивно arr.length = 0 // реактивно

Вирішена проблема: масиви тепер працюють повністю нативно.


3. Проблема: вкладені об'єкти

У Vue 2

Під час ініціалізації Vue рекурсивно проходив по всіх полях об'єкта, щоб "обгорнути" їх у гетери/сетери. Це було:

  • Повільно при великих даних.
  • Неможливо для об'єктів, доданих пізніше.
javascript
this.obj = { nested: { value: 1 } } // obj.nested не реактивний, поки не пройшов через defineReactive()

У Vue 3

Proxy створює реактивність ліниво (on demand): під час першого звернення до вкладеного об'єкта він автоматично обгортається в Proxy.

javascript
const state = reactive({ nested: { count: 0 } }) state.nested.count++ // реактивно, навіть якщо об'єкт вкладений

Вирішена проблема: миттєва реактивність на будь-якому рівні вкладеності.


4. Проблема: неможливість відстежувати колекції (Map, Set, WeakMap)

У Vue 2

Ці структури даних взагалі не могли бути реактивними, оскільки Object.defineProperty() не може перехоплювати їхні методи (set, get, add, delete).

У Vue 3

Proxy перехоплює методи колекцій через спеціальні пастки. Тепер можна спокійно використовувати реактивні Map і Set:

javascript
const map = reactive(new Map()) map.set('key', 'value') // реактивно map.delete('key') // реактивно

Вирішена проблема: можна використовувати сучасні структури даних з повною реактивністю.


5. Проблема: зайві оновлення і втрати продуктивності

У Vue 2

Система залежностей Dep працювала на рівні властивості, і іноді підписники спрацьовували зайвий раз, навіть якщо значення не змінилося.

javascript
this.value = 10 this.value = 10 // все одно тригерить оновлення!

У Vue 3

Нова система track() / trigger() стала гранулярною і точною:

  • Vue порівнює старе і нове значення.
  • Відстежує залежності за конкретним ключем.
  • Мінімізує повторні оновлення.

Вирішена проблема: менше непотрібних перерендерів, вища продуктивність.


6. Проблема: неможливість використовувати реактивність поза компонентом

У Vue 2

Реактивність була тісно пов'язана з життєвим циклом компонентів. Ти не міг створити "реактивний стан" поза компонентом без внутрішнього API.

У Vue 3

Реактивність винесена в окремий пакет @vue/reactivity, і доступна через ref(), reactive(), computed(), watchEffect().

javascript
// можна використовувати навіть без Vue-компонента import { reactive, watchEffect } from 'vue' const state = reactive({ count: 0 }) watchEffect(() => { console.log(state.count) }) state.count++ // реактивно навіть у Node.js

Вирішена проблема: реактивність стала універсальною, незалежною від компонентів.


7. Проблема: продуктивність під час ініціалізації

У Vue 2

Щоб зробити об'єкт реактивним, Vue проходив по всіх його властивостях і викликав Object.defineProperty() на кожній. Якщо data було великим, компонент монтувався повільно.

У Vue 3

Proxy не вимагає проходу по властивостях, Vue створює один проксі-об'єкт і обробляє звернення "за запитом".

Вирішена проблема: ініціалізація компонентів стала в рази швидшою.


8. Проблема: непрозорість налагодження і передбачуваності

У Vue 2

У деяких випадках реактивність працювала "магічно": неможливо було точно зрозуміти, де що тригериться, особливо при Vue.set().

У Vue 3

Нова система прозора:

  • Є окремі низькорівневі API (effect, track, trigger).
  • Можна легко логувати і дебажити залежності.
  • DevTools показує детальну карту реактивних зв'язків.

Вирішена проблема: краще розуміння і контроль над реактивністю.


Підсумок: які проблеми вирішує Proxy

ПроблемаVue 2Vue 3 (Proxy)
Додавання/видалення властивостейНіТак
Робота з масивамиЧастковоПовністю
Вкладені об'єктиНеавтоматичноАвтоматично
Підтримка Map/SetНіТак
Продуктивність під час створенняНизькаВисока
Гранулярність відстеженняГрубаТочна
Використання поза компонентамиНіТак
Прозорість налагодженняОбмеженаВідмінна

Коротко

Нова реактивна система Vue 3 на Proxy вирішила головні проблеми старої версії, зробила реактивність універсальною, масштабованою, швидкою і точною, зберігши при цьому простоту декларативного стилю Vue.

Коротка відповідь

Для співбесіди
Premium

Коротка відповідь допоможе вам впевнено відповідати на цю тему під час співбесіди.