vue双向数据绑定
介绍:
vue.js是采用数据劫持结合发布者-订阅者模式
的方式,通过object.defineProperty()
,来劫持各个属性的getter
和setter
,在数据变动时发布消息给订阅者,触发相应的监听回调来渲染视图。
这个过程基本上分为四步:
第一步: 需要Observer
的数据对象进行递归遍历,包括子属性对象的属性,都加上setter
和getter
,这样的话,给这个对象的某个值赋值,就会触发setter
,那么就能监听到了数据变化。
第二步: 通过Compile
解析模板指令,将模板中的变量替换成数据,然后初始化渲染页面视图,并将每个指令对应的节点绑定更新函数,添加监听数据的订阅者,一旦数据有变动,收到通知,更新视图
第三步: Watcher
订阅者是Observer
和Compile
之间通信的桥梁。
主要做的事情有:
1、在自身实例化时往属性订阅器(dep)里面添加自己
2、自身必须有一个update()
方法
3、待属性变动时dep.notice()
通知时,能调用自身的update()
方法,并触发Compile
中绑定的回调,则功成身退。
第四步: MVVM
作为数据绑定的入口,整合Observer、Compile、Watcher
三者,通过Observer
来监听自己的model
数据变化,通过Compile
来解析编译模板指令,最终利用Watcher
搭起Observer
和Compile
之间的通信桥梁,达到数据变化->视图更新;视图交互变化(input)->数据model变更的双向绑定效果。
注:Object.defineProperty()是用来做什么的?它可以来控制一个对象属性的一些特有操作,比如读写权、是否可以枚举,这里我们主要先来研究下它对应的两个描述属性get和set,
<script>
// defineProperty三个参数 第一个目标对象、第二个要修改的对象、第三个目标属性拥有的特新
var Book={}
var name=''
Object.defineProperty(Book,'name',{
set:function(value){
name=value;
console.log('你取一个书名叫做'+value) //你取一个书名叫做你的指南
},
get:function(){
return '《'+name+'》'
}
})
Book.name='你的指南'
console.log(Book.name) //《你的指南》
</script>
实现过程
首先要对数据进行劫持监听,所以我们需要设置一个监听器Observer
,用来监听所有的属性。如果属性上发生变化了,就需要告诉订阅者Watcher
看是否需要更新。因为订阅者是有很多个,所以我们需要有一个消息订阅器Dep来专门收集这些订阅者,然后在监听器Observer
和订阅者Watcher
之间进行统一管理的。接着,我们还需要有一个指令解析器Compile
,对每个节点元素进行扫描和解析,将相关指令对应初始化成一个订阅者Watcher
,并替换模板数据或者绑定相应的函数,此时当订阅者Watcher
接收到相应属性的变化,就会执行对应的更新函数,从而更新视图。因此接下去我们执行以下3个步骤,实现数据的双向绑定: