Vue
Основы реактивности
Классический баг эпохи jQuery: счётчик корзины показывает 2, а в данных уже 3, потому что в одном из пяти мест обновить надпись забыли. Реактивность Vue убирает этот класс ошибок целиком. Разработчик меняет одно значение - quantity.value = 3 - и каждый кусочек интерфейса, который это значение использует, обновляется сам. Не нужно искать все надписи и трогать DOM руками. Под капотом это работает через JavaScript Proxy, который Vue 3 поставил в основу системы в 2020 году.
- Счётчик уведомлений в шапке обновляется сам, как только приходит новое сообщение, без ручного поиска элемента в DOM
- Итоговая сумма заказа пересчитывается при каждом изменении количества товара без единой строки кода синхронизации
- Подсветка активного пункта меню переключается автоматически при смене маршрута через реактивное состояние
- Фильтры в каталоге: меняется одно реактивное условие, и отфильтрованный список перерисовывается сам
- Темизация: смена реактивного флага тёмной темы мгновенно перекрашивает все компоненты, подписанные на него
Предварительные знания
- Понимание SFC и блока script из урока vue-03
- JavaScript: объекты, свойства, методы массивов, замыкания на уровне идеи
- Знакомство с интерполяцией и директивами из урока vue-04
- Общее понимание DOM как дерева, которое нужно обновлять при изменении данных
Зачем нужна реактивность
Главная боль ручной работы с DOM это рассинхрон: данные в памяти изменились, а интерфейс показывает старое значение, потому что какое-то место забыли обновить. Чем больше мест зависит от одного значения, тем выше шанс ошибки. Реактивность переворачивает подход: разработчик объявляет связь один раз, и дальше система сама поддерживает интерфейс в соответствии с данными.
Переменная count используется в трёх местах шаблона: в тексте абзаца, в условии бейджа и неявно в кнопке. При нажатии меняется только одно значение, а Vue сам обновляет все три места. Нет ни одной строки вида найди элемент и поменяй текст. Это и есть выигрыш: один источник правды вместо россыпи ручных обновлений.
Та же идея односторонней синхронизации лежит и в основе React, но реализована иначе. React пересобирает описание интерфейса целиком при изменении состояния и сравнивает результат. Vue точечно отслеживает, какое значение где читается, и перерисовывает только зависимые места. Разные механизмы, общая цель - убрать ручную синхронизацию.
Какую конкретную проблему решает реактивность по сравнению с ручным обновлением DOM?
Как Vue отслеживает зависимости через Proxy
Vue 3 строит реактивность на встроенном в JavaScript объекте Proxy. Proxy это обёртка над обычным объектом, которая перехватывает обращения к его свойствам. Когда какой-то эффект (например, рендеринг компонента) читает реактивное свойство, Vue это фиксирует: запоминает, что этот эффект зависит от этого свойства. Когда свойство меняется, Vue знает, какие эффекты нужно перезапустить.
Два ключевых слова в этой системе: track (отследить чтение) и trigger (запустить обновление). При чтении свойства срабатывает track и связывает текущий эффект со свойством. При записи срабатывает trigger и перезапускает все эффекты, которые это свойство читали. Поэтому обновляются только зависимые части интерфейса, а не весь компонент целиком без разбора.
Vue 2 использовал другой механизм - Object.defineProperty, который не мог отследить добавление новых свойств в объект и работу с массивами по индексу. Proxy в Vue 3 снял эти ограничения: он перехватывает любые операции, включая добавление и удаление свойств.
Как Vue 3 узнаёт, какие части интерфейса нужно обновить при изменении значения?
Декларативный рендеринг и первый взгляд на ref и reactive
Реактивность делает возможным декларативный рендеринг. Императивный подход это пошаговые команды: найди элемент, поменяй текст, потом ещё один. Декларативный подход это описание желаемого результата: при таком состоянии интерфейс выглядит так. Vue берёт описание из шаблона, связывает его с реактивным состоянием и сам поддерживает соответствие. Разработчик думает о том, что показать, а не о том, как именно менять DOM.
- Императивный (старый jQuery-подход) — Найти узел, изменить его текст, повторить для каждого зависимого места вручную. Легко забыть одно из мест и получить рассинхрон.
- Декларативный (Vue) — Описать в шаблоне связь между значением и разметкой один раз. Vue сам обновляет все места при изменении значения.
Чтобы значение стало реактивным, его нужно создать через специальную функцию. Vue даёт две: ref и reactive. Функция ref оборачивает любое значение, включая примитивы вроде числа или строки, и в скрипте к нему обращаются через свойство .value. Функция reactive делает реактивным объект целиком, но работает только с объектами, не с примитивами. Детальное сравнение и подводные камни разбираются в следующем уроке.
В шаблоне ref автоматически разворачивается: пишут count, а не count.value. Свойство .value нужно только в скрипте. Это частый источник путаницы у новичков, и следующий урок разбирает почему так устроено и когда что выбирать.
Что значит декларативный рендеринг в контексте Vue?
Связь с другими темами
Этот урок про интуицию реактивности. Дальше идём в конкретные инструменты:
- ref и reactive — Два способа создать реактивное состояние, на которых строится вся работа с данными в компоненте
- computed — Производные значения, которые пересчитываются только когда меняются их реактивные зависимости
- Синтаксис шаблонов — Директивы и интерполяция автоматически реагируют на изменения реактивного состояния
Итог
- Реактивность убирает ручную синхронизацию интерфейса с данными: разработчик меняет значение, а Vue сам обновляет все места, где оно используется
- Декларативный рендеринг значит, что разработчик описывает, как интерфейс должен выглядеть при текущем состоянии, а не пишет пошаговые команды обновления DOM
- Vue 3 строит реактивность на JavaScript Proxy: обращение к свойству отслеживается, а его изменение запускает обновление зависимых эффектов
- Система запоминает, какой кусочек интерфейса какое значение читает, и при изменении значения перерисовывает только зависимые части
- ref оборачивает любое значение и требует .value в скрипте, reactive делает реактивным объект напрямую - детали в следующем уроке
Связанные уроки
- vue-06-ref-reactive — Этот урок даёт интуицию реактивности, а следующий разбирает конкретные инструменты ref и reactive в деталях
- vue-04-template-syntax — Директивы из урока о шаблонах автоматически перерисовываются именно благодаря системе реактивности
- vue-07-computed — computed строится поверх отслеживания зависимостей, описанного здесь