Що робить watch()?
1. Що робить watch()
watch() стежить за змінами реактивних значень (створених через ref, reactive, computed тощо)
і виконує вказану функцію лише тоді, коли ці значення дійсно змінюються.
Синтаксис:
watch(source, callback, options?)source- за чим стежимо (ref,reactive, функція або масив).callback(newValue, oldValue)- викликається при зміні.options- додаткові налаштування (immediate,deep,flushта ін).
2. Найпростіший приклад
import { ref, watch } from 'vue'
const count = ref(0)
watch(count, (newVal, oldVal) => {
console.log(`count змінився: ${oldVal} → ${newVal}`)
})
count.value++ // викликає callbackТут watch() "підписується" на зміну count.value.
Коли значення змінюється - викликається callback.
3. Як це працює всередині
Під капотом watch() створює ефект (effect), як і computed, але з поведінкою "лише при зміні".
- Vue запам'ятовує, які реактивні дані використовувалися у функції-джерелі (
source). - При зміні цих даних Vue викликає callback.
- Vue порівнює старе і нове значення (shallow-порівняння).
- Якщо значення змінилося - виконується твоя логіка.
4. Приклад з об'єктом reactive
import { reactive, watch } from 'vue'
const user = reactive({
name: 'Tim',
age: 25
})
// Стежимо за всім об'єктом
watch(user, (newUser, oldUser) => {
console.log('user змінився:', newUser)
})Але важливо:
При відстеженні об'єкта
reactiveзміни всередині об'єкта не спрацюють за замовчуванням, якщо не вказати{ deep: true }.
Правильно:
watch(user, (newVal, oldVal) => {
console.log('user змінився глибоко:', newVal)
}, { deep: true })5. Стежити за конкретною властивістю
Замість цілого об'єкта можна передати функцію - "селектор".
watch(
() => user.name, // відстежуємо лише name
(newName, oldName) => {
console.log(`Ім'я змінилося: ${oldName} → ${newName}`)
}
)Це кращий спосіб - він продуктивний і точковий.
6. Опції watch()
| Опція | Опис | Приклад |
|---|---|---|
immediate: true | Виконати callback одразу під час ініціалізації (з поточним значенням) | watch(count, cb, { immediate: true }) |
deep: true | Стежити за всіма вкладеними змінами об'єкта/масиву | watch(user, cb, { deep: true }) |
flush | Визначає коли виконується watcher відносно рендера. | watch(value, cb, { flush: 'post' }) |
onCleanup(fn) | Дозволяє задати очищення побічного ефекту перед наступним викликом | див. нижче |
7. Очищення побічних ефектів
Часто в watch() потрібно очищати таймери, підписки тощо.
Vue передає в callback функцію onCleanup, щоб очистити попередній ефект:
watch(searchQuery, (newQuery, oldQuery, onCleanup) => {
const controller = new AbortController()
fetch(`/api?q=${newQuery}`, { signal: controller.signal })
// скасовуємо попередній запит, якщо значення знову змінилося
onCleanup(() => controller.abort())
})8. Спостереження за кількома джерелами
Можна стежити одразу за кількома значеннями, передавши масив:
const first = ref('Tim')
const last = ref('Cook')
watch([first, last], ([newFirst, newLast], [oldFirst, oldLast]) => {
console.log(`Ім'я: ${oldFirst} ${oldLast} → ${newFirst} ${newLast}`)
})Vue відстежує всі залежності, і callback викликається, якщо змінилося хоча б одне з них.
9. Різниця між watch() та watchEffect()
| Критерій | watch() | watchEffect() |
|---|---|---|
| Що відстежує | Конкретні реактивні значення або функції | Все, що використовується всередині ефекту |
| Коли викликається | Лише при зміні значень | Одразу під час запуску і при кожній зміні |
Є oldValue | Так | Ні |
| Тонкий контроль | Так (можна вказати deep, immediate) | Ні, все автоматично |
| Типовий випадок | Реагувати на зміну стану | Виконувати побічні ефекти при будь-якій зміні |
Приклад:
// watch()
watch(count, (newVal, oldVal) => console.log(newVal))
// watchEffect()
watchEffect(() => {
console.log(count.value)
})10. Приклад з практики
Наприклад, ти хочеш реагувати на зміну пошукового рядка, але не при кожному рендері:
const query = ref('')
watch(query, async (newQuery) => {
results.value = await fetch(`/api?q=${newQuery}`).then(r => r.json())
}, { immediate: true })Тут immediate: true дає перший запит під час монтування компонента,
а потім watch() спрацьовує лише при зміні query.
11. Коротко і просто
watch()- це "реактивний слухач": він відстежує конкретні дані і викликає функцію при їхній зміні.
Ти використовуєш його, коли потрібно виконати дію, а не просто оновити інтерфейс.
Приклад для запам'ятовування
| Що робиш | Що використовувати |
|---|---|
| Хочу, щоб інтерфейс сам оновився при зміні даних | reactive() / ref() / computed() |
| Хочу виконати побічний ефект при зміні даних (наприклад, API-запит, лог, таймер, локалстор) | watch() |
Коротка відповідь
Для співбесідиКоротка відповідь допоможе вам впевнено відповідати на цю тему під час співбесіди.