Запропонувати правкуПокращити цю статтюДопрацюйте відповідь до «Що робить watch()?». Ваші зміни проходять модерацію перед публікацією.Потрібне підтвердженняКонтентЩо ви змінюєте🇺🇸EN🇺🇦UAПереглядЗаголовок (UA)Коротка відповідь (UA)**`watch()`** стежить за змінами реактивних значень (створених через `ref`, `reactive`, `computed` тощо) і виконує вказану функцію лише тоді, коли ці значення дійсно змінюються. **Ключове:** ти використовуєш його, коли потрібно виконати дію (наприклад, API-запит), а не просто оновити інтерфейс.Показується над повною відповіддю для швидкого нагадування.Відповідь (UA)Зображення## 1. Що робить `watch()` `watch()` **стежить за змінами реактивних значень** (створених через `ref`, `reactive`, `computed` тощо) і виконує вказану функцію **лише тоді**, коли ці значення дійсно змінюються. ### Синтаксис: ```javascript watch(source, callback, options?) ``` - `source` - за чим стежимо (`ref`, `reactive`, функція або масив). - `callback(newValue, oldValue)` - викликається при зміні. - `options` - додаткові налаштування (`immediate`, `deep`, `flush` та ін). --- ## 2. Найпростіший приклад ```javascript 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`, але з поведінкою "лише при зміні". 1. Vue запам'ятовує, які реактивні дані використовувалися у функції-джерелі (`source`). 2. При зміні цих даних Vue викликає callback. 3. Vue порівнює старе і нове значення (shallow-порівняння). 4. Якщо значення змінилося - виконується твоя логіка. --- ## 4. Приклад з об'єктом `reactive` ```javascript import { reactive, watch } from 'vue' const user = reactive({ name: 'Tim', age: 25 }) // Стежимо за всім об'єктом watch(user, (newUser, oldUser) => { console.log('user змінився:', newUser) }) ``` Але важливо: > При відстеженні об'єкта `reactive` зміни **всередині** об'єкта не спрацюють за замовчуванням, > якщо не вказати `{ deep: true }`. Правильно: ```javascript watch(user, (newVal, oldVal) => { console.log('user змінився глибоко:', newVal) }, { deep: true }) ``` --- ## 5. Стежити за конкретною властивістю Замість цілого об'єкта можна передати функцію - "селектор". ```javascript 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`, щоб очистити попередній ефект: ```javascript watch(searchQuery, (newQuery, oldQuery, onCleanup) => { const controller = new AbortController() fetch(`/api?q=${newQuery}`, { signal: controller.signal }) // скасовуємо попередній запит, якщо значення знову змінилося onCleanup(() => controller.abort()) }) ``` --- ## 8. Спостереження за кількома джерелами Можна стежити одразу за кількома значеннями, передавши масив: ```javascript 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`) | Ні, все автоматично | | Типовий випадок | Реагувати на зміну стану | Виконувати побічні ефекти при будь-якій зміні | Приклад: ```javascript // watch() watch(count, (newVal, oldVal) => console.log(newVal)) // watchEffect() watchEffect(() => { console.log(count.value) }) ``` --- ## 10. Приклад з практики Наприклад, ти хочеш реагувати на зміну пошукового рядка, але не при кожному рендері: ```javascript 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()` |Для рев’юераПримітка для модератора (необов’язково)Бачить лише модератор. Прискорює рев’ю.