vue 3 的 ref 修改通过调度机制在微任务中批量更新:赋值仅标记依赖并去重入队,由 flushjobs 统一执行,确保同 tick 内多次修改只触发一次更新。

Vue 3 的 ref 本身不“在微任务队列中合并修改”,真正做合并的是响应式系统背后的调度机制——它自动把多次对同一个或多个 ref 的赋值,收拢到一次微任务中统一执行更新。
ref 修改触发的是“标记+入队”,不是立即更新
当你写 count.value++ 或 name.value = 'Alice',Vue 做的只是:
- 通知所有依赖这个
ref的 effect(比如组件 render、computed、watch)需要重新运行 - 把对应的更新任务(job)加入一个全局异步队列
- 如果同一 job 已在队列里,就跳过重复添加(靠唯一 id 去重)
微任务阶段统一 flush 所有 pending job
Vue 使用 Promise.resolve().then(flushJobs) 或 queueMicrotask(flushJobs) 把队列刷新逻辑推入微任务。这意味着:
递归分析 Vue 项目组件依赖,从入口文件生成组件层级图,支持 Vue 2/3,输出组件名、文件路径和属性。适用于分析组件结构、排查依赖或了解项目架构。
- 不管你在同步代码里改了 1 次还是 10 次
ref,只要在同一个 tick 内,最终只执行一次flushJobs -
flushJobs会按顺序执行所有已入队的 job,此时读取到的ref.value是最终值 - 组件渲染、计算属性重求值、watch 回调等,都在这一步批量发生
你不需要手动“合并 ref 修改”,但要注意边界情况
正常情况下,你只需照常赋值,合并由框架保障。但以下情况会影响预期效果:
- 跨 tick 修改:比如加了
await nextTick()或setTimeout,就会分两次 flush - 用
markRaw包裹的对象,其内部属性变更不会触发响应式通知 - 直接替换整个 ref(
obj.value = {...})会触发一次更新;而深层修改(obj.value.items.push(x))只要对象仍是 reactive,也会被正确追踪并合并在同一批
本质上,ref 是响应式数据的入口,而合并行为藏在 trigger → queueJob → flushJobs 这条链路里。你写的每一行赋值,都在为这次批量更新“投票”,而不是各自“开工”。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!









