vue监听实现原理
Vue 监听实现原理
Vue 的监听机制主要依赖于 Object.defineProperty 或 Proxy(Vue 3+)来实现数据的响应式。以下是核心实现原理:
数据劫持
通过 Object.defineProperty(Vue 2)或 Proxy(Vue 3)劫持数据的读取和修改操作。当数据被访问或修改时,触发对应的 getter 和 setter。
// Vue 2 实现
Object.defineProperty(obj, key, {
get() {
// 依赖收集
return val;
},
set(newVal) {
// 触发更新
val = newVal;
}
});
依赖收集
在 getter 中,通过 Dep 类收集当前正在执行的 Watcher(依赖)。每个响应式属性都有一个对应的 Dep 实例,用于管理所有依赖它的 Watcher。
class Dep {
constructor() {
this.subs = [];
}
addSub(sub) {
this.subs.push(sub);
}
notify() {
this.subs.forEach(sub => sub.update());
}
}
派发更新
在 setter 中,当数据变化时,通过 Dep.notify() 通知所有依赖的 Watcher 执行更新。Watcher 会重新计算或触发组件的重新渲染。
set(newVal) {
if (val === newVal) return;
val = newVal;
dep.notify(); // 通知更新
}
异步更新队列
Vue 通过异步队列(如 nextTick)优化多次数据变更的更新。同一事件循环内的多次数据修改会合并为一次更新,避免不必要的重复渲染。
queueWatcher(watcher) {
// 将 Watcher 加入队列,异步执行
nextTick(flushSchedulerQueue);
}
Vue 3 的改进
Vue 3 使用 Proxy 替代 Object.defineProperty,解决了 Vue 2 中无法监听数组索引和对象新增属性的问题。Proxy 可以直接拦截整个对象的操作,无需递归遍历属性。

// Vue 3 实现
const proxy = new Proxy(obj, {
get(target, key) {
track(target, key); // 依赖收集
return target[key];
},
set(target, key, value) {
target[key] = value;
trigger(target, key); // 触发更新
return true;
}
});
总结
- Vue 2 通过
Object.defineProperty实现数据劫持,结合Dep和Watcher完成依赖收集与派发更新。 - Vue 3 使用
Proxy提供更全面的拦截能力,优化响应式系统的性能和功能。






