flush 控制 watch 和 watchEffect 回调执行时机:pre(默认,更新前)、post(DOM 更新后)、sync(立即同步);推荐按需选用 post 或 watchPostEffect 处理 DOM 操作,避免滥用 sync。

Vue 3 中,flush 是 watch 和 watchEffect 的关键配置项,用来精准控制侦听回调的执行时机——它不改变“是否触发”,而是决定“什么时候触发”,尤其在响应式数据变化与 DOM 更新之间存在异步队列时,这个控制非常必要。
flush 的三种取值及对应行为
pre(默认):数据变更后、组件更新前执行回调。
此时 DOM 还未刷新,能读取变更前的 DOM 状态(比如元素尺寸、文本内容),适合做状态快照或避免重复渲染判断。
post:数据变更后、DOM 更新完成再执行回调。
此时可安全访问最新渲染结果,例如调用 element.getBoundingClientRect()、聚焦输入框、滚动到新内容等 DOM 操作。
sync:数据一变就立即同步执行回调,跳过 Vue 的异步批处理队列。
会破坏性能优化机制,可能引发重复执行或竞态问题,仅在极少数必须强同步的底层逻辑中考虑,日常开发应避免。
如何在 watch 中使用 flush
直接在 watch 的第三个参数中传入 { flush: 'post' } 等选项:
将静态 Vue 页面(index.vue)改造为动态页面(Custom.vue);稿源仅限 index.vue、其引用的 CSS 与资源路径,禁止参考仓库内其他文件。Invoke when user wants to transform a static Vue page into a dynamic data-driven page with Element UI components.
- 监听单个 ref:
watch(count, callback, { flush: 'post' }) - 监听多个源(数组):
watch([a, b], ([newA, newB], [oldA, oldB]) => {}, { flush: 'post' }) - 配合
immediate使用时,flush同样生效:watch(data, cb, { immediate: true, flush: 'post' })—— 初始化时也会等待首次渲染完成后再执行回调
watchEffect 与更简洁的替代写法
watchEffect 默认也是 flush: 'pre',但 Vue 提供了语义更明确的封装:
-
watchPostEffect(cb)等价于watchEffect(cb, { flush: 'post' }),推荐用于 DOM 操作场景,代码意图更清晰 -
watchSyncEffect(cb)等价于watchEffect(cb, { flush: 'sync' }),极少使用,需格外谨慎
它们都自动追踪依赖,无需显式指定监听源,适合逻辑简单、依赖明确的副作用。
实际开发中的选择建议
多数情况下不需要改 flush,保持默认即可;有明确 DOM 交互需求时再调整:
- 要读旧 DOM 或避免重绘 → 用默认
pre - 要操作新 DOM(如 focus、scroll、测量)→ 明确设为
post或用watchPostEffect - 遇到异步请求被覆盖、回调顺序错乱等问题,先检查是否误用了
sync,而不是加nextTick补救
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!









