Vue响应式系统核心是数据劫持+依赖收集+派发更新:通过Object.defineProperty(Vue2)或Proxy(Vue3)拦截读写,在getter中收集依赖(Watcher),setter中通知更新,配合异步队列实现高效视图刷新。

Vue 的响应式系统核心是通过 数据劫持 + 依赖收集 + 派发更新 实现的。它让开发者写普通 JS 对象,却能自动追踪变化、更新视图——不是靠脏检查,也不是靠编译时静态分析,而是运行时对数据访问和修改做精准拦截。
数据劫持:用 Object.defineProperty 或 Proxy 拦截读写
Vue 2 使用 Object.defineProperty 为 data 对象每个属性添加 getter/setter;Vue 3 改用 Proxy,支持数组索引、新增/删除属性等更完整的响应式场景。
- getter 中触发「依赖收集」:记录当前正在执行的渲染函数(Watcher)是谁
- setter 中触发「派发更新」:通知所有依赖该属性的 Watcher 重新求值
- 对象嵌套时,会递归遍历并响应式化所有层级(Vue 2 需手动
Vue.set处理新增属性;Vue 3 的 Proxy 天然支持)
依赖收集:谁在用这个数据?记下来
当组件首次渲染时,模板中的表达式(如 {{ count }})会作为 Watcher 运行,访问 this.count —— 此刻触发 getter,把当前 Watcher 记入该属性的依赖列表(Dep)中。
- 每个响应式属性对应一个 Dep 实例,内部维护一个 Watcher 数组
- 计算属性(computed)、watch、模板插值都会创建各自的 Watcher,并参与收集
- 收集只发生在「响应式读取」期间,赋值或纯逻辑运算不触发
派发更新:数据变了,通知相关视图重算
当修改 this.count = 5,setter 被调用,Dep 通知所有关联 Watcher 执行 update 方法。
立即学习“Java免费学习笔记(深入)”;
- Watcher 默认异步更新(加入 microtask 队列),避免重复渲染
- 更新时重新执行渲染函数,生成新 VNode,再由 patch 算法比对差异、操作真实 DOM
- 如果依赖的是计算属性,它的 getter 会先重新求值,再触发依赖它的 Watcher 更新
数据绑定不只是响应式:还包括编译与指令解析
v-model、v-bind、v-on 等指令在模板编译阶段被解析成渲染函数中的逻辑,最终都落到响应式数据的读写上。
-
v-model="msg"编译后等价于:value="msg" @input="msg = $event.target.value" -
v-bind:title="title"在渲染时读取this.title,触发 getter 收集依赖 - 所有绑定都建立在响应式数据基础上,没有响应式,绑定就只是静态快照
基本上就这些。它不复杂,但容易忽略细节:比如非响应式初始值、异步更新队列、依赖收集的时机。理解了这三层,你就看懂了 Vue 怎么让“数据变,视图动”这件事真正落地。











