Назад к вопросам
Middle
283
questionbank

Как работает реактивность в Vue.js?

Sobes Copilot

Получайте ответы в реальном времени

Ответ от нейросети

sobes.tech AI

Реактивность во Vue.js основана на паттерне "наблюдатель" (Observer).

Когда создается экземпляр Vue, он проходит по всем свойствам в объекте data и преобразует их в геттеры и сеттеры с использованием Object.defineProperty в Vue 2 или Proxy в Vue 3.

Vue 2:

  • При доступе к свойству (геттер) Vue отслеживает, какой компонент его использует.
  • При изменении свойства (сеттер) Vue уведомляет все компоненты, которые его отслеживали, о необходимости обновления (перерисовать шаблон).

Vue 3:

  • Использует Proxy для перехвата всех операций с объектом (добавление, удаление свойств, изменение значений и т.д.), обеспечивая более полную реактивность по сравнению с Vue 2.
  • Благодаря Proxy, реактивность Vue 3 не имеет ограничений Vue 2 (не требуется $set для добавления новых свойств).

Ключевые компоненты реактивности:

  • Observer: Преобразует свойства данных в геттеры/сеттеры (Vue 2) или обрабатывает их с помощью Proxy (Vue 3).
  • Dep (Dependency): Объект, ассоциированный с каждым реактивным свойством, который хранит список зависимых Watcher'ов.
  • Watcher: Представляет компонент, вычисляемое свойство или watchers, которые зависят от реактивных данных. Когда данные меняются, Watcher уведомляется и запускает соответствующее действие (например, перерисовку компонента).

Пример (Vue 2):

// Внутренняя реализация (упрощенно)
function defineReactive(obj, key, val) {
  let dep = new Dep(); // Создаем Dep для свойства

  Object.defineProperty(obj, key, {
    enumerable: true,
    configurable: true,
    get: function reactiveGetter() {
      // Если есть глобальный Watcher (при отрисовке компонента)
      if (Dep.target) {
        dep.depend(); // Добавляем Watcher в список зависимостей Dep
      }
      return val;
    },
    set: function reactiveSetter(newVal) {
      if (newVal === val) return;
      val = newVal;
      dep.notify(); // Уведомляем все зависимые Watcher'ы
    }
  });
}

// Как это выглядит в компоненте
new Vue({
  data: {
    message: 'Hello' // defineReactive будет применено к message
  },
  template: '<div>{{ message }}</div>' // При доступе к message, Watcher этого template добавится в Dep message
});