vue为啥能实现监听
Vue 监听机制的核心原理
Vue 实现监听的核心依赖于 JavaScript 的 Object.defineProperty(Vue 2.x)或 Proxy(Vue 3.x)特性。通过劫持数据对象的属性访问和修改,触发依赖收集与更新通知。
基于 Object.defineProperty 的实现(Vue 2.x)
通过定义属性的 getter 和 setter 拦截操作:
- 依赖收集:在
getter中记录当前依赖(如 Watcher 实例)。 - 触发更新:在
setter中通知依赖进行更新,执行重新渲染或回调函数。
示例代码逻辑:
function defineReactive(obj, key) {
let value = obj[key];
const dep = new Dep(); // 依赖管理容器
Object.defineProperty(obj, key, {
get() {
if (Dep.target) dep.depend(); // 收集依赖
return value;
},
set(newVal) {
if (newVal === value) return;
value = newVal;
dep.notify(); // 通知更新
}
});
}
基于 Proxy 的实现(Vue 3.x)
Proxy 提供更全面的拦截能力,支持数组和动态新增属性:
- 拦截操作:代理对象的读取(
get)、修改(set)、删除(deleteProperty)等操作。 - 性能优化:避免递归遍历对象属性,按需响应。
示例代码逻辑:
const reactive = (target) => {
return new Proxy(target, {
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;
}
});
};
依赖管理机制
- Watcher 与 Dep:每个响应式属性关联一个
Dep实例,用于存储依赖的Watcher(如组件渲染函数、计算属性等)。 - 派发更新:数据变化时,
Dep通知所有Watcher执行更新,可能触发虚拟 DOM 的重新渲染或用户定义的回调。
数组的特殊处理
Vue 2.x 中通过重写数组方法(如 push、pop)实现监听:

const arrayProto = Array.prototype;
const arrayMethods = Object.create(arrayProto);
['push', 'pop'].forEach(method => {
const original = arrayProto[method];
arrayMethods[method] = function(...args) {
const result = original.apply(this, args);
this.__ob__.dep.notify(); // 手动触发更新
return result;
};
});
总结对比
- Vue 2.x:基于
Object.defineProperty,需递归初始化属性,对数组需特殊处理。 - Vue 3.x:基于
Proxy,支持动态属性,性能更高,但需环境支持 ES6。






