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

Як влаштована реактивність Vue 3 під капотом і що робить nextTick?

Основа - Proxy і два хуки: track і trigger.

  • reactive() загортає об'єкт у Proxy. Обробник get викликає track: запам'ятовує, що поточний «ефект» (рендер компонента, computed, watch) читає це поле.
  • Обробник set викликає trigger: знаходить усі ефекти, що читали поле, і планує їх перезапуск.
  • ref робить те саме через геттер і сеттер на .value - тому він працює з примітивами, які проксувати неможливо.
// спрощено
const state = new Proxy(target, {
  get(obj, key) { track(obj, key); return obj[key]; },
  set(obj, key, value) { obj[key] = value; trigger(obj, key); return true; },
});

Рендер компонента - теж ефект: під час рендеру він «підписується» рівно на ті поля, які прочитав шаблон. Зміна поля, якого шаблон не читає, рендер не запускає.

Планувальник і nextTick. Зміни не перемальовують DOM одразу. Vue збирає всі ефекти, які треба перезапустити, у чергу й виконує їх один раз в мікрозадачі. Десять змін поспіль - один рендер.

Звідси nextTick: одразу після зміни стану DOM ще старий.

items.value.push(newItem);
await nextTick();
listEl.value.lastElementChild.scrollIntoView(); // DOM уже оновлено

Наслідки для продуктивності:

  • Глибока реактивність проксує вкладені об'єкти ліниво, при доступі. Великі незмінні дані (результат API на тисячі рядків) дешевше тримати в shallowRef, де відстежується лише заміна .value.
  • markRaw позначає об'єкт, який Vue ніколи не має робити реактивним: екземпляри сторонніх бібліотек, карти, редактори.

Докладніше в документації: Реактивність у деталях

Перевір себе

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

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