一聚教程网:一个值得你收藏的教程网站

最新下载

热门教程

Vue.js 响应式系统中副作用函数 Effect 的触发时机

时间:2026-07-04 11:53:47 编辑:袖梨 来源:一聚教程网

effect 在创建时立即执行一次以完成依赖收集,后续仅在所读响应式数据变更且已被收集依赖时,由 scheduler 决定同步或异步执行;组件中 watchEffect 首次执行于挂载前,后续触发不受挂载状态影响。

Vue.js 响应式系统中,副作用函数(effect)的触发时机不是“一改就立刻执行”,而是由依赖收集、数据变更和调度器三者共同决定的。核心在于:effect 只在它所读取的响应式数据发生变更时被通知,并按调度策略执行——默认同步,但可异步批量处理。

effect 创建时立即执行一次

调用 effect(fn) 时,Vue 会立即执行传入的函数(即 run()),完成首次求值并触发依赖收集。这是初始化行为,不依赖后续变化。

  • 例如:effect(() => console.log(state.count)) 会在定义时打印当前 count 值
  • 此时 state.count 被读取,Proxy 的 get 拦截器调用 track,将该 effect 记入 count 对应的依赖池

数据变更后触发重新执行

当 effect 内部读取过的响应式属性被修改(如 state.count = 5),set 拦截器会调用 trigger,查找该属性对应的依赖池,从中取出所有 effect 并安排执行。

  • 触发前提是:该属性确实被某个 effect 在其 fn 中访问过(即已收集依赖)
  • 若 effect 中未读取某响应式字段,即使该字段变化,也不会触发它
  • trigger 不直接运行 effect,而是交由调度逻辑决定执行方式

执行时机由 scheduler 控制

默认情况下,没有配置 scheduler 的 effect 会被 同步执行;但 Vue 内部组件更新等场景都使用了自定义 scheduler,实现异步批量更新。

立即学习“前端免费学习笔记(深入)”;

  • 例如 runtime-core 中的 scheduler 会把多个 effect 推入 Promise 微任务队列,在 next tick 统一执行,避免重复渲染
  • watchEffect 或 computed 的刷新时机(如 flush: 'post')也依赖 scheduler 实现 DOM 更新后的延迟执行
  • 手动传入 scheduler 时,effect.run() 被替换为 scheduler() 调用,开发者可完全控制执行节奏

组件生命周期中的实际表现

在 setup 中使用的 watchEffect 或 computed,其触发时机还受组件挂载状态影响:

  • watchEffect 首次执行发生在组件实例创建完成、DOM 挂载前(类似 onBeforeMount)
  • 后续触发仅响应其内部读取的响应式数据变化,与组件是否 mounted 无关
  • 如果 effect 依赖的 ref 或 reactive 尚未初始化(如异步加载中),首次执行可能读到 undefined,需做空值判断

热门栏目