watcheffect 的 flush 选项控制副作用回调执行时机:'pre'在渲染前执行(读旧dom),'post'在dom更新后执行(读真实尺寸),'sync'立即同步执行(慎用)。

watchEffect 中的 flush 选项,是用来决定副作用回调在响应式数据变化后、何时执行的关键配置。它不改变监听逻辑,只调整执行时机,直接影响你能否读到更新前/后的 DOM 或状态。
flush 的三种取值和实际效果
Vue 默认使用 flush: 'pre',但你可以显式指定其他两种模式:
- 'pre':在组件重新渲染(DOM 更新)之前 执行回调。此时能拿到旧 DOM 状态,适合做条件判断或避免重复操作。
-
'post':在组件完成渲染、DOM 已更新之后 执行回调。适合需要访问真实尺寸、位置、或依赖最终渲染结果的场景(比如调用
element.getBoundingClientRect())。 - 'sync':数据一变就立即同步执行,跳过 Vue 的异步调度队列。极少使用,可能打断批处理、影响性能,仅用于极特殊同步逻辑(如与非 Vue 系统强耦合)。
怎么写才生效
直接在 watchEffect 的第二个参数里传入对象即可:
watchEffect(() => {
console.log('我被触发了')
}, {
flush: 'post' // 或 'pre' / 'sync'
})
注意:不能写成 flush: "post" 以外的字符串,也不能漏掉大括号。如果只传一个函数,flush 就是默认的 'pre'。
常见误用和坑点
- 异步代码中访问的响应式数据,不会被自动追踪 —— 因为依赖收集只发生在回调同步执行阶段。await 后面的
state.xxx改变,不会触发当前 watchEffect 重新运行。 -
'post' 不等于 nextTick,但它效果接近:Vue 内部会在 nextTick 的微任务阶段执行 'post' 回调,所以你不需要额外套一层
nextTick。 - 多个 watchEffect 共享同一 flush 模式时,Vue 会按顺序批量执行它们;但混用 'pre' 和 'post' 时,'pre' 总是先于 'post' 执行。
什么时候该选哪个
- 想读更新前的 DOM 或跳过一次无效更新 → 选 'pre'
- 要拿元素高度、动画起始位置、第三方库初始化 → 选 'post'
- 调试依赖触发链路 → 配合
onTrigger+ 'pre' 更易定位 - 除非明确知道后果,否则避开 'sync'
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!










