Scheduler: батчинг обновлений, flush pre/post/sync
↑ 7.1 Vue под капотом · ← Предыдущая · → Следующая
Зачем это на собесе
Объясняет, почему DOM обновляется не сразу и зачем нужен
nextTick.
Батчинг
Несколько изменений состояния подряд не вызывают несколько рендеров. Vue ставит компонент в очередь и обновляет один раз за тик (микрозадача).
const count = ref(0)
count.value++
count.value++
count.value++ // рендер будет один
await nextTick() // DOM уже обновлёнОчереди
- pre — колбэки
watchсflush: 'pre'(по умолчанию), до рендера компонента; - render — обновление компонентов (родитель раньше ребёнка, отсортировано по id);
- post —
flush: 'post',onMounted/onUpdated: DOM уже готов; - sync —
flush: 'sync', срабатывает мгновенно при изменении.
watch(source, cb) // pre
watch(source, cb, { flush: 'post' }) // после обновления DOM
watch(source, cb, { flush: 'sync' }) // синхронно (осторожно)
watchPostEffect(() => { /* DOM готов */ })nextTick
Возвращает промис, который разрешается после текущего flush. Нужен, когда после изменения состояния надо прочитать обновлённый DOM (размеры, фокус).
Нюансы
syncможет вызывать каскады и падение производительности;- обновление родителя, не затрагивающее props ребёнка, не перерисовывает ребёнка;
- рекурсивные обновления ограничены (лимит 100) с предупреждением.
Вопросы с ответами
Почему после изменения ref DOM ещё старый?
Обновление отложено в очередь (микрозадача). Дождитесь
await nextTick().
Чем pre отличается от post?
pre выполняется до обновления DOM компонента, post — после, когда можно читать актуальные размеры.