Proxy і нова система реактивності
1. Проблема: неможливість відстежувати нові властивості
У Vue 2
Реактивність створювалася за допомогою Object.defineProperty().
Вона "обгортала" лише наявні поля на момент ініціалізації.
data() {
return { user: { name: 'Tim' } }
}
this.user.age = 30 // не реактивно!
Vue.set(this.user, 'age', 30) // потрібно вручнуУ Vue 3
Proxy перехоплює всі операції get, set, delete,
тому Vue автоматично відстежує нові поля:
const user = reactive({ name: 'Tim' })
user.age = 30 // реактивно!
delete user.name // теж реактивно!Вирішена проблема: можна додавати/видаляти властивості динамічно, без Vue.set().
2. Проблема: слабка робота з масивами
У Vue 2
Масиви не були повністю реактивними:
-
Зміна за індексом не відстежувалася:
javascriptthis.items[2] = 'new' // не спрацює -
Доводилося використовувати
Vue.set(this.items, 2, 'new'). -
Vue "патчив" (
override) методи масивів (push,pop,splice), що було громіздко і знижувало продуктивність.
У Vue 3
Proxy перехоплює всі операції з масивами, зокрема індекси і довжину.
const arr = reactive(['a', 'b'])
arr[1] = 'x' // реактивно
arr.push('c') // реактивно
arr.length = 0 // реактивноВирішена проблема: масиви тепер працюють повністю нативно.
3. Проблема: вкладені об'єкти
У Vue 2
Під час ініціалізації Vue рекурсивно проходив по всіх полях об'єкта, щоб "обгорнути" їх у гетери/сетери. Це було:
- Повільно при великих даних.
- Неможливо для об'єктів, доданих пізніше.
this.obj = { nested: { value: 1 } }
// obj.nested не реактивний, поки не пройшов через defineReactive()У Vue 3
Proxy створює реактивність ліниво (on demand):
під час першого звернення до вкладеного об'єкта він автоматично обгортається в Proxy.
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:
const map = reactive(new Map())
map.set('key', 'value') // реактивно
map.delete('key') // реактивноВирішена проблема: можна використовувати сучасні структури даних з повною реактивністю.
5. Проблема: зайві оновлення і втрати продуктивності
У Vue 2
Система залежностей Dep працювала на рівні властивості,
і іноді підписники спрацьовували зайвий раз, навіть якщо значення не змінилося.
this.value = 10
this.value = 10 // все одно тригерить оновлення!У Vue 3
Нова система track() / trigger() стала гранулярною і точною:
- Vue порівнює старе і нове значення.
- Відстежує залежності за конкретним ключем.
- Мінімізує повторні оновлення.
Вирішена проблема: менше непотрібних перерендерів, вища продуктивність.
6. Проблема: неможливість використовувати реактивність поза компонентом
У Vue 2
Реактивність була тісно пов'язана з життєвим циклом компонентів. Ти не міг створити "реактивний стан" поза компонентом без внутрішнього API.
У Vue 3
Реактивність винесена в окремий пакет @vue/reactivity,
і доступна через ref(), reactive(), computed(), watchEffect().
// можна використовувати навіть без 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 2 | Vue 3 (Proxy) |
|---|---|---|
| Додавання/видалення властивостей | Ні | Так |
| Робота з масивами | Частково | Повністю |
| Вкладені об'єкти | Неавтоматично | Автоматично |
| Підтримка Map/Set | Ні | Так |
| Продуктивність під час створення | Низька | Висока |
| Гранулярність відстеження | Груба | Точна |
| Використання поза компонентами | Ні | Так |
| Прозорість налагодження | Обмежена | Відмінна |
Коротко
Нова реактивна система Vue 3 на
Proxyвирішила головні проблеми старої версії, зробила реактивність універсальною, масштабованою, швидкою і точною, зберігши при цьому простоту декларативного стилю Vue.
Коротка відповідь
Для співбесідиКоротка відповідь допоможе вам впевнено відповідати на цю тему під час співбесіди.