Sobes.tech
Back to questions
Middle
201
questionbank

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

Sobes Copilot

Get answers in real time

Answer from AI

sobes.tech AI

Реактивность во Vue.js основана на системе отслеживания зависимостей property.

При создании экземпляра Vue, данные в data преобразуются в реактивные. Для примитивов (string, number, boolean) используется Object.defineProperty (во Vue 2) или Proxy (во Vue 3) для перехвата операций get и set. Для объектов и массивов также применяется обход свойств и замена методов массива, чтобы они уведомляли об изменениях.

Когда свойство читается в template или computed property, создается зависимость. Внутренний механизм Vue (Watcher) запоминает, какой watcher зависит от данного свойства.

При изменении реактивного свойства, его сеттер уведомляет всех зависимых watcher'ов. Watcher'ы, в свою очередь, запускают пересчет computed properties или перерисовку компонентов.

Во Vue 3 используется Proxy API, что обеспечивает более полную реактивность, включая добавление, удаление и изменение элементов массива по индексу.

Ключевые компоненты:

  • Observer/Reactive Proxy: Преобразует данные в реактивные, отслеживая get и set.
  • Dep (Dependency): Класс, который собирает watcher'ы, зависящие от конкретного свойства.
  • Watcher: Сущность, которая следит за изменением свойства и запускает действие (пересчет или перерисовка).

Пример работы во Vue 2 с Object.defineProperty:

// Внутренний механизм Vue
function defineReactive(obj, key, val) {
  // Создаем объект Dep для данного свойства
  const dep = new Dep();

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

Пример работы во Vue 3 с Proxy:

// Внутренний механизм Vue с использованием Proxy
function createReactiveObject(target) {
  return new Proxy(target, reactiveHandlers); // reactiveHandlers содержат логику get/set
}

const reactiveHandlers = {
  get(target, key, receiver) {
    track(target, 'get', key); // Отслеживаем чтение свойства
    return Reflect.get(target, key, receiver);
  },
  set(target, key, value, receiver) {
    const result = Reflect.set(target, key, value, receiver);
    trigger(target, 'set', key, value); // Запускаем обновление
    return result;
  }
};