vue利用“发布者-订阅者模式”和数据劫持实现双向数据绑定。
发布者
- 新建一个订阅者数组
- 遍历绑定数据的所有子属性,利用
Object.defineProperty()
对属性进行get、set的改写。 - 在get方法中,每当调用get,调用者就是订阅者,就添加这个订阅者到订阅者数组 -- addSub(dep.target)。并将数据返回。
- 在set方法中,调用订阅者数组的
notify
方法通知每一个订阅者。并更新model中的属性。
订阅者存储--dep
- 如果一个个找到订阅者调用
update
方法,会很麻烦,所以将订阅者存储到一个数组中。 - addSub方法,当触发发布者的get方法,就会触发addSub方法,将订阅者添加到订阅者数组中
- notify方法,当触发发布者的set方法时,就会触发此方法,遍历所有订阅者,调用它们的update方法。
订阅者--Watcher
- update方法:调用run方法
- run方法:调用get方法,获取新值,更新值
- get方法:将订阅者数组的target指向自己,dep.target = this。设置value,触发发布者的get方法,就会将此订阅者绑定到订阅者数组中。将target置空,返回value
所以:当数据更新时,触发发布者的set方法 --> 触发订阅者数组的notify方法 --> 触发每个订阅者的update方法 --> 触发run方法 --> 触发订阅者get方法
compile
- 将所有节点转换为文档碎片,以便更新后同时添加到html中,减少回流此时
- 遍历文档碎片,如果是元素节点,遍历其属性,找到绑定数据的属性,分类处理
- 如果是文档属性,并且使用{{}}绑定数据,更新其值
- 最后将更新后的文档碎片添加到原根节点中