Как дождаться перерендера шаблона после изменения реактивных данных во Vue
Что проверяют
Понимаете ли вы, что Vue обновляет DOM не сразу после изменения данных, а пачкой в микротаске. Следом обычно спрашивают, чем nextTick отличается от setTimeout и почему он не ждёт загрузку данных.
Как отвечать
Сначала механизм. При изменении реактивного значения Vue не трогает DOM синхронно: он ставит обновление компонента в очередь планировщика и применяет её в микротаске. Десять присваиваний подряд дают одну перерисовку, поэтому сразу после count.value++ в DOM ещё старое значение.
Инструменты во Vue 3:
nextTick:import { nextTick } from 'vue', затемawait nextTick(). Промис разрешится, когда очередь обновлений будет применена. В Options API то же делаетthis.$nextTick();watchсflush: 'post': колбэк вызывается уже после обновления DOM, есть и сокращениеwatchPostEffect. Удобно, когда реагировать нужно на каждое изменение источника;onUpdated: хук после любой перерисовки компонента. Срабатывает на всё подряд, поэтому им пользуются редко;- шаблонные ссылки: элемент под
v-ifпоявится вrefтолько послеnextTick. Типичный пример: показать поле ввода и сразу поставить на него фокус.
Добавьте про тесты: в Vue Test Utils trigger и setValue возвращают промис, и await на них равносилен ожиданию nextTick.
Где спотыкаются
Отвечают кодом Vue 2: new Vue({ data }) и глобальный Vue.nextTick. Поддержка Vue 2 закончилась в конце 2023 года, во Vue 3 nextTick импортируется из пакета.
Ждут от nextTick завершения запроса или асинхронного компонента. Он дожидается только применения текущей очереди обновлений, а данные, которые ещё грузятся, в DOM не появятся.
Путают обновление DOM с отрисовкой. После nextTick узлы уже изменены и размеры можно измерить, но кадр браузер ещё не нарисовал, поэтому для запуска анимации нужен requestAnimationFrame.