Комментарии (1)
Ответ сгенерирован нейросетью и может содержать ошибки
В чем разница между computed и watch?
Это вопрос о Vue.js. computed и watch — оба инструмента для реакции на изменения данных, но используются в разных сценариях. Это важные концепции реактивности Vue.
computed — вычисляемые свойства
computed используется для вычисления значения на основе других реактивных данных. Результат кэшируется, пока зависимости не изменятся.
// Vue 3 (Composition API)
import { ref, computed } from 'vue'
const firstName = ref('John')
const lastName = ref('Doe')
// Вычисляемое свойство
const fullName = computed(() => {
console.log('вычисляется...') // Логирует только при изменении firstName или lastName
return firstName.value + ' ' + lastName.value
})
console.log(fullName.value) // "John Doe"
console.log(fullName.value) // "John Doe" (используется кэшированное значение, перевычисляется не будет)
firstName.value = 'Jane' // Изменяем зависимость
console.log(fullName.value) // "Jane Doe" (вычисляется заново)
Свойства computed:
- Кэширование — результат сохраняется, перевычисляется только при изменении зависимостей
- Декларативный — описываешь что вычислять, а не как это делать
- Реактивное — автоматически зависит от других данных
- Возвращает значение — используется как переменная
- Синхронное — вычисляется немедленно
Options API вариант:
export default {
data() {
return {
firstName: 'John',
lastName: 'Doe'
}
},
computed: {
fullName() {
return this.firstName + ' ' + this.lastName
}
}
}
В шаблоне:
<template>
<div>
<p>{{ fullName }}</p> <!-- "John Doe" -->
</div>
</template>
watch — наблюдатели
watch используется для выполнения побочных эффектов (side effects) в ответ на изменение данных. Это функция, которая запускается при изменении.
// Vue 3 (Composition API)
import { ref, watch } from 'vue'
const firstName = ref('John')
const lastName = ref('Doe')
const fullName = ref('')
// Наблюдатель
watch(
firstName, // Что наблюдаем
(newValue, oldValue) => { // Что делаем при изменении
console.log(`Имя изменилось с ${oldValue} на ${newValue}`)
fullName.value = newValue + ' ' + lastName.value
}
)
firstName.value = 'Jane' // Логирует: "Имя изменилось с John на Jane"
Свойства watch:
- Побочные эффекты — выполняет код, имеющий сторонние эффекты
- Императивный — описываешь что именно делать при изменении
- Доступ к старому значению — можешь сравнить старое и новое
- Асинхронный — может содержать async код
- НЕ возвращает значение — просто выполняет действие
Options API вариант:
export default {
data() {
return {
firstName: 'John',
lastName: 'Doe',
fullName: ''
}
},
watch: {
firstName(newValue, oldValue) {
console.log(`Имя изменилось с ${oldValue} на ${newValue}`)
this.fullName = newValue + ' ' + this.lastName
}
}
}
Сравнение: computed vs watch
| Критерий | computed | watch |
|---|---|---|
| Назначение | Вычисление значения | Побочные эффекты |
| Кэширование | Да, пока зависимости не изменятся | Нет |
| Синхронность | Синхронное | Асинхронное допускается |
| Возврат значения | Да, возвращает значение | Нет, просто выполняет код |
| Производительность | Выше (кэш) | Ниже (запускается всегда) |
| Параметры колбэка | (oldValue, newValue) | (newValue, oldValue) |
| Множественные зависимости | Да | Нужен массив |
Примеры использования
1. computed — ТА БУДЕ ИСПОЛЬЗОВАТЬ в 80% случаев
Этот вариант лучше:
const firstName = ref('John')
const lastName = ref('Doe')
// ✅ Правильно — используем computed
const fullName = computed(() => firstName.value + ' ' + lastName.value)
template: '<p>{{ fullName }}</p>' // Просто используем как переменная
Плюсы:
- Кэширование (быстрее)
- Проще (описываешь что вычислять)
- Реактивно в шаблонах
2. watch — для побочных эффектов
Этот случай требует watch:
const searchQuery = ref('')
const results = ref([])
const isLoading = ref(false)
// ✅ Правильно — используем watch для API запроса
watch(
searchQuery,
async (newQuery) => {
if (!newQuery) {
results.value = []
return
}
isLoading.value = true
try {
const response = await fetch(`/api/search?q=${newQuery}`)
results.value = await response.json()
} catch (error) {
console.error('Ошибка поиска:', error)
} finally {
isLoading.value = false
}
},
{ debounce: 300 } // Опция для debounce
)
Почему watch: Нужно выполнить асинхронный API запрос — это побочный эффект.
3. watch с глубокими объектами
const user = ref({ name: 'John', age: 30 })
// watch не видит изменения внутри объекта
watch(user, () => {
console.log('пользователь изменился')
})
user.value.name = 'Jane' // НЕ запустит watch
// Нужна опция deep: true
watch(
user,
() => {
console.log('пользователь изменился')
},
{ deep: true } // Следить за вложенными изменениями
)
user.value.name = 'Jane' // Теперь запустит watch
4. Наблюдение за несколькими свойствами
watch(
[firstName, lastName], // Массив зависимостей
([newFirst, newLast], [oldFirst, oldLast]) => {
console.log(`Изменилось: ${oldFirst}/${oldLast} -> ${newFirst}/${newLast}`)
}
)
Опции watch
watch(
searchQuery,
async (newQuery) => { /* ... */ },
{
immediate: true, // Запустить сразу при создании
deep: true, // Следить за вложенными изменениями
flush: 'post', // Запустить после обновления DOM
debounce: 300, // Ждать 300ms после последнего изменения
}
)
Когда использовать что?
Используй computed для:
- Вычисления производных значений (fullName, filterList, count)
- Форматирования данных (дата, валюта, текст)
- Логических выражений (isAdmin, isVisible)
- Когда результат должен быть в реактивной переменной
Используй watch для:
- API запросов
- Логирования
- Изменения несвязанных данных
- Интеграции с внешними библиотеками
- Побочных эффектов
Anti-pattern: не делай так
// ❌ ПЛОХО — используешь watch вместо computed
const fullName = ref('')
watch([firstName, lastName], ([first, last]) => {
fullName.value = first + ' ' + last
})
// ✅ ХОРОШО — используешь computed
const fullName = computed(() => firstName.value + ' ' + lastName.value)
// ❌ ПЛОХО — используешь computed для побочных эффектов
const results = computed(async () => {
return await fetch(...).then(r => r.json())
})
// ✅ ХОРОШО — используешь watch
watch(searchQuery, async (query) => {
results.value = await fetch(...).then(r => r.json())
})
Вывод
- computed — для вычисления значений (детерминированные, кэшируемые)
- watch — для реакции на изменения (побочные эффекты)
В 80% случаев используешь computed, в 20% — watch. Если не уверен — начни с computed, потом перейди на watch если нужны побочные эффекты.