vue 响应式实现
Vue 响应式实现原理
Vue 的响应式系统通过数据劫持结合发布-订阅模式实现,核心是利用 Object.defineProperty(Vue 2.x)或 Proxy(Vue 3.x)拦截数据变化,触发依赖更新。
Vue 2.x 实现方式
数据劫持
通过 Object.defineProperty 递归遍历对象属性,将属性转换为 getter/setter:
function defineReactive(obj, key, val) {
Object.defineProperty(obj, key, {
get() {
console.log('读取属性', key);
return val;
},
set(newVal) {
if (newVal !== val) {
console.log('更新属性', key);
val = newVal;
// 触发依赖更新
dep.notify();
}
}
});
}
依赖收集
每个属性维护一个 Dep 实例(依赖管理器),在 getter 中收集当前依赖(Watcher):
class Dep {
constructor() {
this.subs = [];
}
addSub(sub) {
this.subs.push(sub);
}
notify() {
this.subs.forEach(sub => sub.update());
}
}
观察者模式
Watcher 实例在初始化时触发 getter,将自身添加到 Dep 中:
class Watcher {
constructor(vm, key, cb) {
this.vm = vm;
this.key = key;
this.cb = cb;
Dep.target = this; // 标记当前 Watcher
this.value = vm[key]; // 触发 getter
Dep.target = null; // 重置
}
update() {
this.cb.call(this.vm, this.vm[this.key]);
}
}
Vue 3.x 实现方式
Proxy 代理
使用 Proxy 直接监听整个对象,避免递归遍历:
function reactive(obj) {
return new Proxy(obj, {
get(target, key, receiver) {
track(target, key); // 依赖收集
return Reflect.get(target, key, receiver);
},
set(target, key, value, receiver) {
Reflect.set(target, key, value, receiver);
trigger(target, key); // 触发更新
return true;
}
});
}
依赖管理
通过 WeakMap 和 Map 建立靶点(target)与键(key)的依赖关系:
const targetMap = new WeakMap();
function track(target, key) {
let depsMap = targetMap.get(target);
if (!depsMap) {
targetMap.set(target, (depsMap = new Map()));
}
let dep = depsMap.get(key);
if (!dep) {
depsMap.set(key, (dep = new Set()));
}
dep.add(activeEffect); // 当前激活的 effect
}
副作用函数
通过 effect 包装响应式操作:

let activeEffect;
function effect(fn) {
activeEffect = fn;
fn(); // 执行时触发 track
activeEffect = null;
}
注意事项
- 数组处理:Vue 2.x 需重写数组方法(如
push、pop)实现响应式,Vue 3.x 的Proxy可直接监听数组变化。 - 性能优化:Vue 3.x 的
Proxy减少了递归劫持的开销,并支持懒代理(按需响应)。 - 嵌套对象:Vue 2.x 需在初始化时递归劫持,Vue 3.x 在访问嵌套属性时才动态代理。
通过上述机制,Vue 实现了数据变化到视图更新的自动同步。






