Отслеживание зависимостей

Vue.js строит свою реактивность на основе механизма отслеживания зависимостей, который позволяет автоматически обновлять пользовательский интерфейс при изменении данных. Центральной концепцией является реактивная система, связывающая состояние приложения с отображением через наблюдение за изменениями.


Реактивные объекты

Для создания реактивного объекта используется функция reactive:

import { reactive } from 'vue';

const state = reactive({
  count: 0,
  user: {
    name: 'Алексей',
    age: 30
  }
});

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

  • Любое чтение свойств реактивного объекта регистрируется как зависимость.
  • Любое изменение свойств автоматически вызывает обновление всех эффектов, которые используют эти свойства.
  • Вложенные объекты тоже становятся реактивными. Изменение state.user.name отследится автоматически.

Эффекты и effect

Эффекты позволяют выполнять функцию при изменении её зависимостей:

import { effect } from 'vue';

effect(() => {
  console.log(`Текущее значение: ${state.count}`);
});
  • При первом выполнении effect Vue регистрирует все используемые свойства как зависимости.
  • Любое последующее изменение этих свойств приведет к повторному вызову функции.

Эффекты могут быть использованы для связывания данных с DOM, вычисляемых значений или побочных эффектов.


Вычисляемые свойства

Вычисляемые свойства (computed) создаются на основе реактивных данных и автоматически пересчитываются при изменении зависимостей:

import { computed } from 'vue';

const doubleCount = computed(() => state.count * 2);

Особенности:

  • Ленивая оценка: вычисляемое свойство пересчитывается только при обращении к нему.
  • Кэширование: если зависимости не изменились, возвращается старое значение, что повышает производительность.
  • Использование computed для сложной логики позволяет минимизировать количество эффектов и обновлений DOM.

Слоты зависимостей и watch

Функция watch позволяет отслеживать изменения конкретного реактивного значения и выполнять побочные действия:

import { watch } from 'vue';

watch(
  () => state.user.age,
  (newAge, oldAge) => {
    console.log(`Возраст изменился с ${oldAge} на ${newAge}`);
  }
);

Особенности watch:

  • Может отслеживать одиночные свойства или целые объекты.
  • Позволяет выполнять асинхронные операции при изменении данных.
  • Предоставляет старое и новое значение, что удобно для ведения логов или реагирования на изменения состояния.

Тонкости реактивности

  1. Массивы и объекты

    • Любые мутации массива (push, pop, splice) отслеживаются.
    • Присвоение новых свойств объекту не будет автоматически реактивным, если объект не был создан через reactive. Для добавления реактивного свойства используют set (в Vue 2) или создают новый объект с новым свойством (Vue 3).
  2. Декомпозиция реактивного объекта

    • Если деструктурировать реактивный объект, прямое присваивание значений может потерять реактивность. Использование toRefs позволяет сохранить реактивные ссылки на отдельные свойства:
    import { toRefs } from 'vue';
    
    const { count } = toRefs(state);
  3. Отслеживание сложных зависимостей

    • Vue умеет отслеживать вложенные объекты и массивы. Однако при работе с deeply nested структурами лучше использовать композиционные функции и watch для избирательного слежения.

Принцип работы реактивной системы

Vue строит реактивность на основе геттеров и сеттеров с использованием Proxy. При чтении свойства:

  1. Активный эффект регистрируется как зависимость этого свойства.
  2. Vue сохраняет связь «свойство → эффекты».

При записи:

  1. Все эффекты, зависимые от измененного свойства, запускаются повторно.
  2. Vue оптимизирует повторные вызовы, объединяя их в одну очередь, чтобы избежать лишних обновлений DOM.

Практические рекомендации

  • Использовать reactive для объектов и массивов, ref для примитивов.
  • Для вычислений, основанных на реактивных данных, применять computed вместо создания эффекта вручную.
  • Для побочных действий на изменения — watch, особенно при асинхронной логике.
  • Разделять состояние и представление через композиционные функции, чтобы упростить отслеживание зависимостей.

Механизм отслеживания зависимостей является сердцем Vue.js и обеспечивает высокую производительность приложения без явного управления обновлениями DOM. Понимание работы реактивности позволяет строить масштабируемые и оптимизированные интерфейсы.