vue数据监听具体实现
Vue 数据监听的具体实现
Vue 的数据监听主要通过 Object.defineProperty(Vue 2.x)或 Proxy(Vue 3.x)实现,核心是依赖收集和派发更新。
Vue 2.x 的实现方式
基于 Object.defineProperty
Vue 2.x 使用 Object.defineProperty 对对象的属性进行劫持,通过 getter 和 setter 实现响应式。
function defineReactive(obj, key, val) {
Object.defineProperty(obj, key, {
enumerable: true,
configurable: true,
get() {
console.log('get', key);
return val;
},
set(newVal) {
if (newVal === val) return;
console.log('set', key);
val = newVal;
}
});
}
依赖收集与派发更新

- 每个响应式属性有一个
Dep实例,用于存储依赖(Watcher)。 - 在 getter 中调用
dep.depend()收集依赖。 - 在 setter 中调用
dep.notify()通知依赖更新。
class Dep {
constructor() {
this.subs = [];
}
depend() {
if (Dep.target) {
this.subs.push(Dep.target);
}
}
notify() {
this.subs.forEach(watcher => watcher.update());
}
}
Vue 3.x 的实现方式
基于 Proxy
Vue 3.x 使用 Proxy 代理整个对象,可以监听动态新增的属性。
function reactive(obj) {
return new Proxy(obj, {
get(target, key, receiver) {
console.log('get', key);
return Reflect.get(target, key, receiver);
},
set(target, key, value, receiver) {
console.log('set', key);
return Reflect.set(target, key, value, receiver);
}
});
}
Effect 与依赖追踪
Vue 3.x 引入 effect 和 track/trigger 机制:

track在 get 时收集依赖。trigger在 set 时触发更新。
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);
}
function trigger(target, key) {
const depsMap = targetMap.get(target);
if (!depsMap) return;
const dep = depsMap.get(key);
if (dep) {
dep.forEach(effect => effect());
}
}
数组的监听
Vue 2.x 通过重写数组方法(如 push、pop)实现监听:
const arrayProto = Array.prototype;
const arrayMethods = Object.create(arrayProto);
['push', 'pop', 'shift'].forEach(method => {
const original = arrayProto[method];
arrayMethods[method] = function(...args) {
const result = original.apply(this, args);
console.log('array method', method);
return result;
};
});
Vue 3.x 的 Proxy 可以直接监听数组变化,无需特殊处理。
总结
- Vue 2.x 使用
Object.defineProperty劫持属性,需递归遍历对象,对数组需特殊处理。 - Vue 3.x 使用
Proxy代理整个对象,支持动态属性监听,性能更优。 - 两者均通过依赖收集(
Dep/track)和派发更新(notify/trigger)实现响应式。






