Чем отличаются computed от watch?

В Vue.js computed и watch используются для реактивного отслеживания изменений данных, но они выполняют разные задачи и применяются в разных контекстах. Несмотря на то, что и computed, и watch реагируют на изменения реактивных свойств, их поведение, назначение и производительность различаются.

Что такое computed?

computed — это вычисляемое свойство, которое зависит от других реактивных данных и автоматически пересчитывается, когда эти данные изменяются. Оно кэшируется, то есть пересчёт происходит только при изменении зависимостей.

export default {
data() {
return {
firstName: 'John',
lastName: 'Doe'
};
},
computed: {
fullName() {
return this.firstName + ' ' + this.lastName;
}
}
}

В этом примере fullName автоматически обновляется, когда меняется firstName или lastName, но не пересчитывается без необходимости — он кэширован до следующего изменения зависимостей.

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

  • Кэширование: computed значение сохраняется, и пересчёт происходит только тогда, когда его зависимости реально изменяются.

  • Используется как свойство: В шаблоне или коде вы обращаетесь к нему как к обычному свойству: this.fullName.

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

Что такое watch?

watch — это способ наблюдать за изменением одного или нескольких реактивных свойств и выполнять какую-либо побочную операцию, когда эти свойства меняются.

export default {
data() {
return {
searchQuery: ''
};
},
watch: {
searchQuery(newVal, oldVal) {
this.fetchResults(newVal);
}
},
methods: {
fetchResults(query) {
// запрос на сервер
}
}
}

Здесь watch следит за searchQuery и вызывает метод fetchResults каждый раз, когда значение searchQuery изменяется.

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

  • Не кэшируется: watch не возвращает значение и не используется для получения данных — он запускает функцию при изменении наблюдаемого свойства.

  • Используется для побочных эффектов: Сюда входят вызовы API, работа с localStorage, манипуляции с DOM, запуск анимаций, асинхронные операции и т. п.

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

Сравнение: computed vs watch

Характеристика computed watch
Назначение Вычисление и кэширование производных значений Реакция на изменения и выполнение побочных действий
--- --- ---
Возвращает значение Да Нет
--- --- ---
Кэшируется Да Нет
--- --- ---
Синтаксис Свойство объекта Функция-наблюдатель
--- --- ---
Подходит для Представления (UI) и логики вычислений Асинхронных операций и внешних эффектов
--- --- ---
Асинхронность Не поддерживает асинхронность напрямую Поддерживает асинхронные функции
--- --- ---
Множественные зависимости Да (Vue сам отслеживает зависимости) Нужно указывать явно или использовать функцию
--- --- ---
Управление вложенными структурами Нет (ограничено) Да (через deep: true)
--- --- ---

Примеры использования

Пример 1: Использование computed для форматирования данных

computed: {
formattedPrice() {
return \`$${this.price.toFixed(2)}\`;
}
}

Здесь мы получаем красиво отформатированную цену. Кэширование важно: если price не изменился — пересчёт не нужен.

Пример 2: Использование watch для API-запроса

watch: {
city(newCity) {
this.getWeatherData(newCity);
}
}

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

Использование watch с дополнительными опциями

Vue позволяет более гибко управлять поведением watch с помощью настроек:

watch: {
user: {
handler(newVal, oldVal) {
this.saveToLocalStorage(newVal);
},
deep: true, // Следить за вложенными изменениями
immediate: true // Запустить сразу при инициализации
}
}
  • deep: true — нужен, если user является объектом или массивом и вы хотите следить за вложенными изменениями.

  • immediate: true — вызывает обработчик сразу при создании компонента (без первого изменения).

Возможность реактивного слежения с функцией

Vue поддерживает формат watch(() => expr, callback) через Composition API:

import { ref, watch } from 'vue';
const count = ref(0);
watch(() => count.value, (newVal, oldVal) => {
console.log(\`Count changed: ${oldVal}  ${newVal}\`);
});

Можно отслеживать выражения, сразу получать старое и новое значение и настраивать поведение так же, как в Options API.

Когда использовать computed

  • Для логики отображения, например, объединения имени и фамилии.

  • Для фильтрации и сортировки массивов.

  • Для получения реактивных значений, производных от других реактивных данных.

  • Когда нужно кэшировать результат для повышения производительности.

Когда использовать watch

  • Когда нужно реагировать на изменения и выполнять действия (например, API-запросы, сохранение в хранилище, валидацию).

  • Когда работаете с асинхронными действиями.

  • Когда нужно следить за вложенными структурами (deep).

  • Когда необходимо реагировать немедленно при загрузке компонента (immediate).