Наблюдатели: watch и watchEffect
Разбираем наблюдатели watch и watchEffect — инструмент для побочных эффектов в ответ на изменение данных, и решаем, чем они отличаются от computed.
watch следит за конкретным источником и вызывает функцию при его изменении, давая старое и новое значение. watchEffect запускается сразу и сам отслеживает все реактивные значения, которые использует.
computed или watch?
Важно не путать их. computed вычисляет значение (например, итог корзины). watch не возвращает значение — он выполняет действие (побочный эффект): запрос к серверу, запись в localStorage, лог. Правило: нужно новое значение — computed; нужно что-то сделать в ответ на изменение — watch.
watch: следим за источником
<script setup>
import { ref, watch } from 'vue'
const query = ref('')
watch(query, (newVal, oldVal) => {
console.log(`Запрос изменился: «${oldVal}» → «${newVal}»`)
// здесь обычно делают fetch к серверу
})
</script>
Первый аргумент — за чем следим (ref, или функция-геттер для свойства), второй — что делать. Колбэк получает новое и старое значения, что удобно для сравнения.
Смоделируем watch на JS
Идею «реагируем на смену значения» можно показать обычным кодом — функция получает старое и новое и реагирует только на реальную смену:
function watch(getValue, callback) {
let oldValue = getValue();
return () => {
const newValue = getValue();
if (newValue !== oldValue) {
callback(newValue, oldValue);
oldValue = newValue;
}
};
}
let status = "offline";
const check = watch(() => status, (n, o) =>
console.log(`Статус: ${o} → ${n}`)
);
check(); // значение не менялось — тишина
status = "online";
check(); // изменилось — сработает
status = "online";
check(); // то же значение — снова тишина
status = "away";
check();
Вывод:
Статус: offline → online Статус: online → away
watchEffect: следит сам
watchEffect не требует указывать источник: он запускается сразу и автоматически отслеживает все реактивные значения, прочитанные внутри. Меняется любое из них — функция выполняется заново:
<script setup>
import { ref, watchEffect } from 'vue'
const count = ref(0)
const step = ref(1)
watchEffect(() => {
// зависит и от count, и от step — Vue определит это сам
console.log(`count=${count.value}, step=${step.value}`)
})
</script>
watch против watchEffect
| watch | watchEffect | |
| Источник | указываешь явно | определяется сам по чтению |
| Старое значение | доступно | недоступно |
| Первый запуск | по умолчанию нет | сразу при создании |
| Когда удобнее | реакция на конкретный источник | эффект от нескольких зависимостей |
Типичные применения
- Запрос к API при смене строки поиска или id (с задержкой/debounce).
- Сохранение состояния в
localStorageпри каждом изменении. - Синхронизация с внешней библиотекой (карта, график).
Итог
watchследит за указанным источником и даёт старое/новое значение.watchEffectзапускается сразу и сам отслеживает использованные внутри реактивные данные.- Наблюдатели — для побочных эффектов, а
computed— для производных значений. - Частые задачи: запросы к API, запись в
localStorage, синхронизация с внешним кодом.