Effect 默认同步执行,但可通过 scheduler 调整为异步、延迟、节流或批量执行;flush 控制回调与 DOM 更新顺序;stop 用于彻底终止 effect。

Effect 的执行时机不是固定不变的,它默认同步触发,但可以通过调度器(scheduler)灵活调整为异步、延迟、节流或批量执行。关键不在“能不能改”,而在于“怎么选、何时用”。
默认是同步执行,但容易被误读
effect 创建后立即运行一次,数据变化时也默认同步重新执行。比如:
- 创建即执行:effect(() => console.log(state.count)) 会立刻打印初始值
- 变更即触发:state.count++ 后,回调马上再执行一次,不等 DOM 更新完成
- 这种同步行为在简单调试时直观,但在真实组件中易导致重复渲染、DOM 访问异常或竞态问题
scheduler 是控制执行节奏的核心开关
传入 scheduler 选项,就能接管 effect 的重执行时机。它接收当前 effect 实例,由你决定何时调用它:
使用 JSON Schema 验证 JSON 数据,从示例 JSON 生成 schema,并将其转换为 TypeScript 接口、Python 数据类或 Markdown 文档。
-
推入微任务队列(Vue 默认更新方式):
scheduler: job => queueJob(job),实现批量合并、去重、DOM 更新后执行 -
宏任务延迟:
scheduler: job => setTimeout(job, 0),让执行落到下一个宏任务,适合解耦逻辑与渲染 -
防抖控制:
scheduler: throttle(job, 100),避免高频状态变化频繁触发 - 手动排队:维护一个 Set 或数组缓存 job,统一在 nextTick 或特定事件后 flush
flush 选项影响依赖更新后的响应顺序
对 watchEffect 或 computed 等封装 API,flush 控制回调与 DOM 更新的相对位置:
立即学习“前端免费学习笔记(深入)”;
- flush: 'pre':在 DOM 更新前执行,适合需要提前干预状态的场景(如权限校验)
- flush: 'post':在 DOM 更新后执行,可安全读取更新后的 ref 元素尺寸或样式
- flush: 'sync':强制同步执行——破坏响应式优化,仅用于极少数必须立即响应的底层逻辑
作用域停止(stop)是彻底终止执行的最终手段
当 effect 不再需要持续响应时,不能只靠 scheduler 延迟,而应主动清理:
- effect 返回的 runner 函数自带 stop 方法:
const stop = effect(fn); stop() - 使用 effectScope 封装多个 effect,调用
scope.stop()一次性释放全部依赖和内存引用 - 组件卸载时 Vue 自动 stop 所有 setup 内创建的 effect,但跨组件或全局逻辑需手动管理

















