Вызывается ли watchEffect сразу или только при изменении данных во Vue
Что проверяют
Понимаете ли вы, как watchEffect собирает зависимости и почему для этого ему нужен немедленный запуск. Следом почти всегда спрашивают разницу с watch и что будет с зависимостями после await.
Как отвечать
Коротко: сразу. Функция выполняется синхронно в момент создания эффекта, и именно первый прогон нужен, чтобы Vue увидела, к каким реактивным значениям вы обратились. Явного списка зависимостей нет, их роль играет всё, что было прочитано во время выполнения. Дальше эффект перезапускается при изменении любой из них, а набор зависимостей пересобирается на каждом прогоне.
Детали, которые стоит назвать:
- батчинг: повторные запуски по умолчанию идут с
flush: 'pre', то есть в очереди перед обновлением компонента. Три изменения подряд в одном тике дадут один перезапуск; - варианты flush:
watchPostEffect(илиflush: 'post') срабатывает после обновления DOM, и его первый прогон тоже откладывается до рендера.watchSyncEffectреагирует синхронно на каждое изменение; - отличие от
watch:watchленивый, колбэк при создании не вызывается, пока не передатьimmediate: true. Зато источник задаётся явно, и колбэк получает новое и старое значение; - очистка: эффект получает аргумент
onCleanup, а с Vue 3.5 есть ещёonWatcherCleanup(). Туда кладут отмену запроса или таймера перед следующим прогоном; - остановка:
watchEffectвозвращает функцию остановки. Эффекты, созданные синхронно вsetup, останавливаются сами при размонтировании, созданные асинхронно нужно останавливать вручную.
Где спотыкаются
Не знают, что после await зависимости не отслеживаются: всё, что прочитано в асинхронной части функции, перезапуск эффекта не вызовет.
Путают с watch и ждут, что watchEffect сработает только при изменении. В итоге логика инициализации выполняется дважды: вручную и в первом прогоне эффекта.
Шлют из эффекта запросы без очистки. При быстрой смене фильтра ответы приходят не по порядку, и старый затирает новый. Нужна отмена через AbortController в onCleanup.