vue 观察者实现
Vue 观察者实现原理
Vue 的观察者模式主要通过 Object.defineProperty 或 Proxy 实现数据劫持,结合发布-订阅模式实现响应式更新。
核心实现步骤
数据劫持
通过 Object.defineProperty 或 Proxy 拦截对象的读写操作,在属性被访问或修改时触发依赖收集和更新。

function defineReactive(obj, key, val) {
Object.defineProperty(obj, key, {
get() {
console.log(`get ${key}:${val}`);
return val;
},
set(newVal) {
if (newVal !== val) {
console.log(`set ${key}:${newVal}`);
val = newVal;
}
}
});
}
依赖收集
每个响应式属性都有一个对应的 Dep 实例,用于存储所有依赖该属性的 Watcher 对象。

class Dep {
constructor() {
this.subscribers = new Set();
}
depend() {
if (activeWatcher) {
this.subscribers.add(activeWatcher);
}
}
notify() {
this.subscribers.forEach(watcher => watcher.update());
}
}
观察者(Watcher)
Watcher 实例会在初始化时执行一次回调函数,触发属性的 getter 从而完成依赖收集。
let activeWatcher = null;
class Watcher {
constructor(vm, fn) {
this.vm = vm;
this.fn = fn;
this.update();
}
update() {
activeWatcher = this;
this.fn.call(this.vm);
activeWatcher = null;
}
}
完整示例
class Vue {
constructor(options) {
this._data = options.data;
this.observe(this._data);
new Watcher(this, () => {
console.log('数据变化了', this._data.message);
});
}
observe(data) {
Object.keys(data).forEach(key => {
let val = data[key];
const dep = new Dep();
Object.defineProperty(data, key, {
get() {
dep.depend();
return val;
},
set(newVal) {
if (newVal !== val) {
val = newVal;
dep.notify();
}
}
});
});
}
}
const vm = new Vue({
data: {
message: 'Hello Vue'
}
});
vm._data.message = 'Hello World'; // 触发更新
Vue 3 的改进
Vue 3 使用 Proxy 代替 Object.defineProperty,解决了以下问题:
- 无法检测新增/删除的属性
- 数组变异方法的拦截
- 性能更好
function reactive(obj) {
return new Proxy(obj, {
get(target, key) {
track(target, key);
return target[key];
},
set(target, key, value) {
target[key] = value;
trigger(target, key);
}
});
}






