vue响应式依赖收集本质是建立数据与使用代码的动态映射:读取时拦截并登记当前activeeffect到属性专属依赖集合,变化时仅通知对应effect执行。

Vue 响应式系统的依赖收集,本质是建立“数据”和“使用数据的代码”之间的动态映射关系:谁读了这个值,Vue 就记下谁;等这个值变了,只通知这些被记下的地方重新执行。
依赖收集发生在“读取时”,不是定义时
它不是一创建响应式对象就扫描所有属性,而是在真正访问某个属性(比如模板里写 {{ count }}、计算属性里用 this.name)的那一刻触发。此时 Vue 拦截读取操作(Vue 2 是 getter,Vue 3 是 Proxy.get),并把当前正在运行的副作用函数(如组件渲染函数、computed 的 getter、watch 的回调)登记到该属性的依赖列表里。
- 没被访问过的属性,不会被任何 Watcher 或 effect 订阅,也就不会响应变化
- 新增属性(如 obj.newKey = 'x')默认不响应,因为没人读过它,没触发收集;Vue 2 需 this.$set,Vue 3 中 Proxy 天然支持新增属性,但前提是它被后续读取过
- 数组索引赋值(arr[0] = x)在 Vue 2 中不触发 getter,所以无法收集;Vue 3 的 Proxy 能拦截,但依然依赖“是否被读取”来决定是否加入依赖
每个响应式字段有自己独立的“通知名单”
Vue 不靠全局广播,而是为每个响应式属性维护一份专属依赖集合。Vue 2 用 Dep 实例 存储 Watcher 列表;Vue 3 用三层结构:WeakMap → Map → Set,即:
- WeakMap 以响应式对象为键,避免内存泄漏
- Map 以属性名(key)为键,对应一个依赖集合
- Set 存放所有依赖该属性的 effect 函数(组件渲染、computed、watch 等)
这样修改 state.count,只会触发依赖它的那些 effect,其他无关逻辑完全不受影响。
递归分析 Vue 项目组件依赖,从入口文件生成组件层级图,支持 Vue 2/3,输出组件名、文件路径和属性。适用于分析组件结构、排查依赖或了解项目架构。
收集靠“活跃副作用”自动登记
Vue 3 引入 activeEffect 全局变量,在进入响应式上下文(如 setup()、computed、watch)时临时绑定当前正在执行的 effect 函数。当访问 state.msg 时,get 拦截器检测到 activeEffect 存在,就把它加进 msg 对应的 Set 里。
- 普通 JS 函数或未包裹在响应式 API 中的代码,即使读了响应式数据,也不会被收集
- computed 和 watch 内部都自动创建自己的 effect,各自独立收集依赖,互不干扰
- ref 的 value 属性也是通过 get/set 访问器实现拦截,同样参与这套依赖追踪机制
收集完,变化时精准点名通知
当你执行 state.count++,Proxy 的 set 拦截器被触发,立即从 targetMap 找到对应 depsMap,再定位到 'count' 的 dep Set,遍历执行其中每个 effect。
- 组件渲染 effect 会重新跑 render,生成新 vnode 并 diff 更新 DOM
- computed effect 会重新求值,并可能触发它自己的依赖更新
- watch effect 会执行回调,并提供新旧值比对
没出现在这个 Set 里的逻辑,一次都不会执行——这才是响应式高效的核心。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!










