Что такое computed и watch? В каких случаях что лучше использовать?
MiddleVue.js #vue #reactivity
Вопрос
Что такое computed и watch во Vue и когда использовать один вместо другого?
Короткий ответ
computed — это производное, кэшируемое реактивное значение, которое пересчитывается только при изменении зависимостей и должно быть чистой функцией без побочных эффектов. watch — это побочный эффект, который выполняется в ответ на изменение реактивных данных (запрос к серверу, запись в localStorage, ручное изменение DOM).
Подробный ответ
computed(() => ...)возвращает реактивную ссылку, значение которой вычисляется из других реактивных данных. Vue кэширует результат и пересчитывает его только когда изменилась хотя бы одна из зависимостей, использованных внутри геттера — при повторных обращениях без изменений возвращается закэшированное значение. Используется, когда нужно получить новое значение, производное от текущего состояния (отфильтрованный список, сумма, форматированная строка).watch(source, callback)запускает callback-функцию с побочным эффектом при изменении отслеживаемого источника. Не возвращает значение для использования в шаблоне — используется, когда на изменение данных нужно что-то сделать: сходить за данными на сервер, записать вlocalStorage, показать уведомление.
Практическое правило: если результат — это значение, которое нужно отобразить или использовать дальше — computed. Если результат — это действие (эффект) — watch.
Пример
<script setup>
import { ref, computed, watch } from 'vue'
const search = ref('')
const users = ref([{ name: 'Alice' }, { name: 'Bob' }])
// computed — производное значение, кэшируется, используется в шаблоне
const filteredUsers = computed(() =>
users.value.filter(u => u.name.toLowerCase().includes(search.value.toLowerCase()))
)
// watch — побочный эффект при изменении search
watch(search, (newValue) => {
fetch(`/api/log-search?q=${newValue}`)
})
</script>
<template>
<input v-model="search" />
<ul>
<li v-for="user in filteredUsers" :key="user.name">{{ user.name }}</li>
</ul>
</template>
Дополнительные вопросы
- Почему
computedне должен содержать побочные эффекты (например, запросы к API)? - Чем
watchотличается отwatchEffect? - Что произойдёт, если внутри
computedвызватьDate.now()илиMath.random()?