Vue原理之观察者模式(发布订阅模式)实现单向数据流

观察者模式中如果是发布订阅模式,就会具备三个东西

1.Ovbserver 观察者
2.Vue 观察主体
3.Dep中心调度器
4.Watcher 订阅者

根据这个图我们使用发布订阅模式来理解一下,首先当vue实例对象的数据发生变化的时候,管擦和这就会观察到Objec.definePproperty中的set方法就会去通知Dep中心调度器,Dep此时就会发布消息,订阅者们就会收到消息并触发订阅方法,例如watcher1订阅了key=name1,watcher3也订阅了key=name1,当name1发生变化的时候Dep就会发布消息,当订阅者接收到信息后就会触发订阅者的update方法进行数据的更新,这是第一条线

第二条线就比较复杂,这里我们要知道一般v-model指令是用在input标签中的,当input中的数据发生变化我们的DOM层的数据发生变化的时候,v-model就会触发订阅者中的方法直接更新data中的数据

对于观察者模式不清晰的可以去看一下前两章观察者模式和观察者模式之发布订阅模式。

使用Vue的时候,我们一般都先new Vue()由此可以判断出Vue是一个构造函数或者一个类,我们就用ES6的类写法来写简单的Vue实现原理。

首先定义一个class Vue类

在vue2中我们Vue实现响应式是通过Objec.definePproperty来实现,所以首先我们先要监听到用户通过new Vue(参数),传递过来的参数。

 这里我们可以看到options就是传递的那个大对象,对象里有两个属性,el和data,Vue中劫持数据又分为了两个部分,两个部分都是劫持new Vue(参数)传递过来的这个大对象,现在我们就要用Objectdefineproperty来劫持,第一部分劫持完后给Vue中的$data添加一遍data属性,让Vue这个大对象中的$data中的数据添加gettter和setter方法。

这里我们可以看到,当我们new Vue的时候就把这个大对象传到了Vue这个类里面,此时options就是这个大对象,后续options就是指new Vue(大对象)中传的这个大对象。首先我们在Vue中可以看到,如果new Vue后,我们是可以通过vue.name1和vue.name2等来直接获取options.data中的数据的,所以此时我们要把options中的data暴露给Vue类,所以就在Vue类中写了this.$data = options.data,此时使用vue.$data就可以获取到name1和name2,这就成功的把options中的数据添加到了vue实例对象中的$data属性中,现在我们获取data中的name1和name2就有了两种方式,第一种就是利用实例vue.$data获取,第二种就是通过vue.name1和vue.name2中获取,第二种就是上述代码的Object.defineproperty所实现的了,这里相当于Vue类中目前私有属性有了三个,第一个是$data第二个是name1第三个是name2,当用户通过vue实例对象去访问name1时,就会触发proxyData中的get方法,怕大家看不懂,我又单独拿出来加了一个简写案例,可以看下图:

这个就是使用Object.defineproperty方法来给obj这个对象添加两个属性,一个是name1,一个是name2,当用户访问obj.name1时就会被监听到,从而调用get方法返回obj.data.name1。好了,简单的就说到这里,回到上面,我们给vue实例对象添加完后

此时输出的结果就是:

这里可以很清晰的看到,我们已经给Vue中的私有属性$data进行了监听,并且给vue实例对象里的里面的数据name1和name2都添加了get和set方法但是这里我们也可以看到,接着我们进行第二部分,第二部分是需要监听vue实例对象里的$data,从而使得当用户要通过vue.$data.name1去访问name1的数据时,可以被监听到,所以我们还要给$data做一个监听。

在Vue主体中写observer方法,用来监听vue.$data中的数据,注意看set(),当观察者监听到vue.$data中的数据发生变化时,也就是触发了set方法,此时Dep就会发布消息告知订阅者,触发订阅者中的方法,注意这里是所有订阅者里面的方法都会被触发,$watcher就是订阅者对象的集合,内部包含了很多订阅者,大概就是{“订阅者1”:[订阅方法1,订阅方法2,update],"订阅者2“:[订阅方法1,订阅方法2,update]}这样的一种形式,当dep通知到我们的订阅者的时候,就会触发订阅者的订阅方法update,这个update就会让视图进行更新

订阅者内部:

以上就完成了单向数据流的实现。

如果是双向数据流,也就是使用了我们的v-model指令给标签进行了绑定,当dom的数据发生改变的时候,我们就可以去获取到dom此时显示的数据,并直接修改data,这个就是双向数据流。

  • 54
    点赞
  • 33
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值