vue实现数据监听原理
Vue 数据监听原理
Vue 的数据监听主要通过 Object.defineProperty 或 Proxy 实现,核心是依赖收集和派发更新。以下是具体实现原理:
数据劫持
Vue 2.x 使用 Object.defineProperty 劫持对象的属性访问和修改。通过递归遍历数据对象的属性,将其转换为 getter/setter,从而在属性被访问或修改时触发依赖收集和更新。

function defineReactive(obj, key, val) {
Object.defineProperty(obj, key, {
enumerable: true,
configurable: true,
get: function reactiveGetter() {
console.log('触发依赖收集');
return val;
},
set: function reactiveSetter(newVal) {
if (newVal === val) return;
console.log('触发更新');
val = newVal;
}
});
}
Vue 3.x 使用 Proxy 实现数据劫持,直接代理整个对象,无需递归遍历属性,性能更好且支持动态新增属性。
const observed = new Proxy(obj, {
get(target, key, receiver) {
console.log('触发依赖收集');
return Reflect.get(target, key, receiver);
},
set(target, key, value, receiver) {
console.log('触发更新');
return Reflect.set(target, key, value, receiver);
}
});
依赖收集
每个响应式数据属性关联一个 Dep 实例(依赖管理器)。在 getter 中,当前正在执行的 Watcher(订阅者)会被添加到 Dep 的订阅列表中。

class Dep {
constructor() {
this.subs = [];
}
addSub(sub) {
this.subs.push(sub);
}
notify() {
this.subs.forEach(sub => sub.update());
}
}
派发更新
当数据修改时,setter 会触发 Dep.notify(),通知所有订阅的 Watcher 执行更新操作。Watcher 可能是组件渲染函数、计算属性或用户自定义的 watch。
class Watcher {
update() {
console.log('执行更新');
}
}
数组监听
Vue 2.x 通过重写数组的变异方法(如 push、pop 等)实现数组监听。调用这些方法时,手动触发更新通知。
const arrayProto = Array.prototype;
const arrayMethods = Object.create(arrayProto);
['push', 'pop', 'shift'].forEach(method => {
arrayMethods[method] = function(...args) {
const result = arrayProto[method].apply(this, args);
console.log('触发数组更新');
return result;
};
});
总结
- Vue 2.x 基于
Object.defineProperty实现数据劫持,需递归遍历对象属性。 - Vue 3.x 使用
Proxy代理整个对象,性能更优且支持动态属性。 - 依赖收集通过
Dep和Watcher实现,数据变化时触发订阅者更新。 - 数组通过重写变异方法实现监听。






