参考
如何理解vue数据双向绑定原理
打在开头。参考大佬的理解自己写了一遍加了点注释而已。做个笔记记录。
关于compile的部分没写。
// Observer 监听器对象,监听对象上的属性是否发生了改变
class Observer {
// 观察data对象上属性的变化,一旦变化,通知Dep
constructor(data) {
this.data = data; //维护data对象
this.walk(data); //walk方法实现对本对象属性的监听
}
walk(data) {
let keys = Object.keys(data); // 获取keys数组
for (let key of keys) {
this.defineReactive(data, key, data[key]);
}
}
defineReactive(data, key, value) {
var dep = new Dep(); //对应本属性的消息中转站
observe(value);// 如果值为对象,实现深度监听
// 通过 defineProperty 实现对属性的监听
Object.defineProperty(data, key, {
enumerable: true,
configurable: true,
get() {
if (Dep.target) {
dep.addSub(Dep.target); // 在消息订阅器中注册
}
return value;
},
set(oldVal) {
if (newval === value) return; // 无变化
value = newval;
observer(newval); // 如果新的值为对象,实现深度监听
dep.notify(); // 将改变报告给消息中转站DEP
}
})
}
observe(value) {
// 判断value是否需要进行深度监听
if (value && typeof value !== 'object') {
new Observer(value);
}
}
}
//消息发布订阅器 Dep
class Dep {
static target = null;
constructor() {
this.subs = [];//维护一个发布列表
}
addSub(sub) {
this.subs.push(sub);
}
notify() {
this.subs.forEach(sub => {
sub.update();
})
}
}
// 消息接收者 Watcher
class Watcher {
constructor(vm, exp, cb) {
this.cb = cb;
this.vm = vm; // 应该是指的vue对象
this.exp = exp;
this.value = this.get();
}
update(){
this.run();
}
run(){
let value = this.vm.data[this.exp];
let oldVal = this.value;
this.cb.call(this.vm,value,oldVal);
}
get(){
Dep.target = this;
let value = this.vm.data[this.exp];
// 此处获取vm.data时,由于data是被监听对象,会调用observer的get
// 设置了Dep.target,实现将该watcher加入到dep的列表中
Dep.target = null;
return value;
}
}
class Compile{
// 扫描绑定的dom节点(el属性)
// 寻找所有的v-指令和{{}}
// 对于v-model的指令,添加input时间响应
// 对于v-on,添加对应时间监听
// 对于textNode,替换掉{{}}内部的内容
}