Vue.js 源码探究:Observer、Dep 和 Watcher 如何实现数据双向绑定
2024-02-05 09:34:32
Vue.js 中的数据双向绑定是一种强大的功能,它允许开发人员轻松地将数据模型与 UI 组件绑定在一起,从而实现数据的自动更新。这种机制背后有三个关键组件:Observer、Dep 和 Watcher。
Observer
Observer 负责监听数据的变化。当数据发生变化时,它会通知所有依赖于该数据的 Watcher。Observer 通过使用 Object.defineProperty 来实现对数据的监听。当数据发生变化时,Observer 会触发 Setter,从而通知所有依赖于该数据的 Watcher。
Dep
Dep 是一个依赖收集器。它负责收集所有依赖于某个数据的 Watcher。当数据发生变化时,Observer 会通知 Dep,Dep 再通知所有依赖于该数据的 Watcher。
Watcher
Watcher 是一个订阅者。它负责监听数据的变化,并在数据发生变化时更新 UI。Watcher 通过使用 addDep() 方法将自己添加到 Dep 中,并在数据发生变化时通过 update() 方法更新 UI。
这三个组件共同协作,实现了 Vue.js 中的数据双向绑定。当数据发生变化时,Observer 会通知 Dep,Dep 再通知所有依赖于该数据的 Watcher,从而更新 UI。
Observer 的实现
Observer 的实现很简单,它通过使用 Object.defineProperty 来实现对数据的监听。当数据发生变化时,Observer 会触发 Setter,从而通知所有依赖于该数据的 Watcher。
class Observer {
constructor(data) {
this.data = data;
this.dep = new Dep();
this.walk(data);
}
walk(data) {
if (typeof data !== 'object' || data === null) {
return;
}
Object.keys(data).forEach(key => {
this.defineReactive(data, key, data[key]);
});
}
defineReactive(data, key, val) {
const dep = this.dep;
Object.defineProperty(data, key, {
get() {
dep.depend();
return val;
},
set(newVal) {
if (val === newVal) {
return;
}
val = newVal;
dep.notify();
}
});
}
}
Dep 的实现
Dep 的实现也很简单,它是一个依赖收集器,负责收集所有依赖于某个数据的 Watcher。当数据发生变化时,Dep 会通知所有依赖于该数据的 Watcher。
class Dep {
constructor() {
this.subs = [];
}
addSub(watcher) {
this.subs.push(watcher);
}
depend() {
if (Dep.target) {
Dep.target.addDep(this);
}
}
notify() {
this.subs.forEach(sub => {
sub.update();
});
}
}
Dep.target = null;
Watcher 的实现
Watcher 的实现稍微复杂一些,它是一个订阅者,负责监听数据的变化,并在数据发生变化时更新 UI。Watcher 通过使用 addDep() 方法将自己添加到 Dep 中,并在数据发生变化时通过 update() 方法更新 UI。
class Watcher {
constructor(vm, exp, cb) {
this.vm = vm;
this.exp = exp;
this.cb = cb;
this.depIds = new Set();
this.value = this.get();
}
addDep(dep) {
if (!this.depIds.has(dep.id)) {
this.depIds.add(dep.id);
dep.addSub(this);
}
}
get() {
Dep.target = this;
const value = this.vm._data[this.exp];
Dep.target = null;
return value;
}
update() {
const oldValue = this.value;
this.value = this.get();
this.cb.call(this.vm, this.value, oldValue);
}
}
总结
Observer、Dep 和 Watcher 是 Vue.js 中数据双向绑定的核心组件。它们通过协同工作,实现了数据双向绑定。Observer 负责监听数据的变化,Dep 负责收集所有依赖于某个数据的 Watcher,Watcher 负责监听数据的变化,并在数据发生变化时更新 UI。