vue 双向数据绑定的实现学习之监听器的实现方法

2020-06-13 10:25:11易采站长站整理

提到了vue实现的基本实现原理:Object.defineProperty() -数据劫持 和 发布订阅者模式(观察者),下面讲的就是数据劫持在代码中的具体实现。

1.先看如何调用

new一个对象,传入我们的参数,这个Myvue ,做了啥?

上面看到了在实例化一个Myvue 对象的时候,会执行init方法, init 方法做了两个事,调用了observer 方法,和 实例化调用了 compile 方法。 到这里我们就明白了,实例化一个Myvue后,我们要做的就是监听数据变化和编译模板 。

上面Object.key() 方法,实例化时传入的data里面对应的变量缓存到 Myvue 对象的 $prop上,这样方便在后续处理数据。怎么个方便法呢!…

2.observer 的实现

  observer ,模式里面的角色定位 他是一个发布者,也可以理解为是一个观察者


function observer (data) {
if(!data || typeof data !== 'object') {
return;
}
Object.keys(data).forEach(key => {
// 对每个属性监听处理
defineReactive(data, key, data[key]);
})
}

  defineReactive


function defineReactive (data,key,value) {
// 每次访问/修改属性的时候 实例化一个调度中心Dep
var dep = new Dep();
Object.defineProperty(data,key,{
get: function() {
// 添加到watcher 的Dep 调度中心
if (Dep.target) { // Dep.target 是个什么鬼? 转到watcher.js 它是某个订阅者 watcher
dep.addSub(Dep.target); //这个代码段的意思: 如果有订阅者(访问/修改属性的时候) 就将这个订阅者统一放进 Dep 调度中心中
}
// console.log(`${key}属性被访问了`)
return value
},
set: function (newValue) {
if (value != newValue) {
// console.log(`${key}属性被重置了`)
value = newValue
dep.notify(); //我这里有做改动了,通知调度中心的notify方法
}
}
})
// 递归调用,observe 这个value
observer(value)
}

  Dep: 这里是所有订阅者的一个调度中心,它不是直接监听 发布者的信息,发布者将要发布的信息 发布到 一个中介、调度中心(Dep),由这个Dep 来调度信息给哪个订阅者(Watcher)


// 统一管理watcher订阅者的Dep (调度中心) Dispatch center
function Dep () {
// 所有的watcher 放进这里统一管理
this.subs = []}
Dep.target = null;
// 通知视图更新dom的 notify的方法
Dep.prototype.notify = function () {
// this.subs 是上面订阅器watcher 的集合