一口气说完Vue的数据绑定原理

本文学习于Vue官网的深入响应式原理以及思否的《剖析Vue原理&实现双向绑定MVVM》,图中代码与Vue的源码仍有出入,但实际流程基本无误。

1.MVVM双向绑定展示

可以大概看出,整改流程分上下两个线路,上面线路讲的是数据的双向绑定,下面线路讲的是视图的更新,本文主要讲的是数据的双向绑定

1、实现一个类数据监听器Observer,能够对数据对象的所有属性进行监听,如有变动可拿到最新值并通知订阅者
2、实现一个指令解析器Compile,对每个元素节点的指令进行扫描和解析,根据指令模板替换数据,以及绑定相应的更新函数
3、实现一个Watcher,作为连接Observer和Compile的桥梁,能够订阅并收到每个属性变动的通知,执行指令绑定的相应回调函数,从而更新视图
4、mvvm入口函数,整合以上三者

2.Vue实现数据绑定的做法

数据劫持: vue.js 则是采用数据劫持结合发布者-订阅者模式的方式,通过Object.defineProperty()来劫持各个属性的settergetter,在数据变动时发布消息给订阅者,触发相应的监听回调。

 3.数据双向绑定的三部分

3.1 监听器Observer
(用来劫持并监听对象所有属性,如果有变动的,就通知订阅者。)

Observer是一个数据监听器,其实现核心方法就是前文所说的Object.defineProperty( )。如果要对所有属性都进行监听的话,那么可以通过递归方法遍历所有属性值,并对其进行Object.defineProperty( )处理。这样的话,给这个对象的某个值赋值,就会触发setter,那么就能监听到了数据变化。

Object.keys(data):返回一个对象里的可以被 for in 到的属性所组成的数组(取的是属性名)。

forEach(function(key){ }):调用数组的每个元素,并传递给回调函数

3.2 消息订阅器Dep
(专门收集这些订阅者,然后在监听器Observer和订阅者Watcher之间进行统一管理的)

订阅器Dep添加一个订阅者设计在getter里面,这是为了让Watcher初始化进行触发,因此需要判断是否要添加订阅者,在setter函数里面,如果数据变化,就会去通知所有订阅者,订阅者们就会去执行对应的更新的函数。

 

 简单的实现了一个消息订阅器(本质是一个数组)用来收集订阅者,数据调用时通过addSub来添加订阅者。数据变动触发notify,再调用订阅者的update方法

 3.3订阅者Watcher

(可以收到属性的变化通知并执行相应的函数,从而更新视图)

Watcher订阅者作为Observer和Compile之间通信的桥梁,主要做的事情是:
1、在自身实例化时往属性订阅器(dep)里面添加自己
2、自身必须有一个update()方法
3、待属性变动dep.notice()通知时,能调用自身的update()方法,并触发Compile中绑定的回调,则功成身退。

 实例化Watcher的时候,调用get()方法,通过Dep.target = watcherInstance标记订阅者是当前watcher实例,强行触发属性定义的getter方法,getter方法执行的时候,就会在属性的订阅器dep添加当前watcher实例,从而在属性值有变化的时候,watcherInstance就能收到更新通知。

 3.4总体实现

可以大概看出数据双向绑定的脉络

1.给data对象每一个属性通过Object.defineProperty( )添加get()以及set()方法

2.在get()方法中通过闭包使用消息订阅器数组添加存放订阅者对象,然后返回属性值

3.在set()方法中通过先判断新旧值是否一致,如果不一致则把新值赋值给属性,并且调用订阅器的notify方法,这个方法会去通知所有订阅者,订阅者们就会去执行对应的更新函数。

注意:Watcher实例是在lifecycle.js文件中创建的,有需要的同学可以参考下源码。

4.关于 Object.defineProperty 的弊端

4.1 无法使用低级浏览器中的方法来实现的,所以Vue不支持IE8以及更低版本的浏览器。

4.2 由于 JavaScript 的限制,Vue 不能检测数组和对象的变化。(下面是我自己做的思维导图,便于大家可以简单理解)

 

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值