flush选项只控制watch回调执行时机:'pre'(默认)在dom更新前执行,可读新数据但拿不到新dom;'post'在dom更新后执行,可安全操作真实dom;'sync'同步执行,破坏批处理优化,仅限调试等特殊场景。

理解 watch 中的 flush 选项,关键在于抓住一点:它不改变“监听什么”,只决定“回调什么时候跑”——而这个“时候”,直接关系到你能不能读到或操作到更新后的 DOM。
flush: 'pre'(默认)——数据已变、DOM 还没动
这是 Vue3 的隐式默认值。回调在组件更新(即 DOM 重绘)之前执行,此时响应式数据已经更新,但页面上的 DOM 还是旧的。
- 能安全访问最新的
ref.value或reactive数据 - 但
ref元素、document.querySelector拿到的仍是上一轮渲染的 DOM 节点 - 适合做清理工作:比如取消上一个未完成的请求、清除定时器、中断动画
- 避免在回调里再改监听源,否则可能触发重复执行或状态错乱
flush: 'post'——DOM 刚刷新完,一切就绪
回调在 Vue 完成 DOM 渲染后、下一个微任务中执行,确保你能拿到真实、最新、已挂载的 DOM 状态。
- 可放心调用
element.getBoundingClientRect()、focus()、scrollIntoView()等依赖布局的操作 - 行为上接近
nextTick(),但语义更明确,且与 watch 生命周期天然对齐 - 典型场景:输入框聚焦、滚动定位、第三方 UI 组件初始化
flush: 'sync'——立刻执行,跳过队列
数据一变,回调立刻同步触发,不等 Vue 批量更新,也不进异步队列。
- 会破坏 Vue 默认的响应式优化机制
- 容易引发重复执行、渲染撕裂,甚至无限循环(比如回调里又改了监听的数据)
- 仅建议用于纯副作用场景:如调试日志、性能埋点、非响应式状态同步
- 日常开发中应尽量避免
本质上,Vue 把所有数据变更攒起来,等同步代码执行完,再一次性更新 DOM。flush 就是在这个流程里插队的位置选择器:选 pre 是抢在 DOM 更新前干预数据逻辑;选 post 是等 DOM 落地后再动手操作;选 sync 是强行打断流程、立刻响应——代价是失去批量优化和稳定性保障。










