Vue响应式系统核心是精准驱动视图更新,通过依赖收集、派发更新和组件级粒度控制实现“按需响应”,并提供渐进可控的设计机制。

Vue.js 响应式系统的核心,是让数据变化自动、精准地驱动视图更新,而不是靠开发者手动刷新或遍历整个 DOM。它不追求“所有地方都响应”,而是坚持“只更新真正用到的地方”——这种克制和精确,正是其设计哲学的起点。
依赖收集:谁在用这个数据?
当组件渲染时,访问 data 或 computed 中的属性,会触发对应的 getter。此时 Vue 会把当前正在执行的渲染函数(即一个 Watcher 或 ReactiveEffect)记下来,存进该属性专属的依赖列表里。
- 每个响应式对象的每个属性,背后都有一个 Dep(或 Vue 3 中的 Set 集合)来管理订阅者
- 数组、Map、Set 等复杂类型也被纳入追踪范围,Vue 3 的 Proxy 能自然捕获新增/删除操作
- 静态模板中未使用的字段不会被收集,也就不会参与后续更新——这是“按需响应”的基础
派发更新:数据变了,通知谁?
当你修改响应式数据(比如 state.count++),setter 或 Proxy 的 set 拦截器会被触发,接着调用 trigger 函数。
递归分析 Vue 项目组件依赖,从入口文件生成组件层级图,支持 Vue 2/3,输出组件名、文件路径和属性。适用于分析组件结构、排查依赖或了解项目架构。
- trigger 不是广播,而是查表:根据目标对象和 key,找到之前存好的依赖集合,逐个通知
- 通知的是副作用函数(effect),不是直接操作 DOM;这些函数可能对应组件渲染、计算属性求值或 watch 回调
- 同一轮更新中多次修改同一属性,只会触发一次更新——靠异步队列(queueJob)合并处理
粒度控制:组件级更新,而非递归刷新
每个组件实例自带一个专属的渲染 effect,它只关心自己模板里用到的数据。父组件数据变,子组件不会无脑重绘。
立即学习“前端免费学习笔记(深入)”;
- 如果子组件模板里没引用父传的某个 prop,那这个 prop 变了,子组件完全不受影响
- 即使深层嵌套,只要中间组件做了 v-once 或使用 shouldUpdate 逻辑,也能跳过 diff
- Vue 3 的 block tree 进一步缩小 diff 范围,只比对动态区块内的节点
设计哲学:渐进可控,不替你做决定
Vue 的响应式不是“越智能越好”,而是提供可预测、可调试、可干预的机制。
- 用 shallowRef 或 markRaw 可以主动退出响应式,避免过度代理
- 计算属性的 dirty 标志位让它惰性求值,没被读取就不执行
- watch 的 flush: 'post' 或 immediate: true 让你明确控制副作用时机

















