参考文档
一、页面—>数据
view更新data只需要添加DOM事件监听即可,比如input标签监听 ‘input’ 事件就可以实现
二、数据—>页面
是通过数据代理 + 发布者-订阅者模式的方式来实现的
2-1 数据代理
vue是通过Object.defineProperty()来实现数据代理的
<!--1.Vue中的数据代理:通过vm对象来代理data对象中属性的操作(读/写)2.Vue中数据代理的好处:更加方便的操作data中的数据3.基本原理:通过Object.defineProperty()把data对象中所有属性添加到vm上。为每一个添加到vm上的属性,都指定一个getter/setter。在getter/setter内部去操作(读/写)data中对应的属性。-->
let number = 18let person = {name: "张三",sex: '男',}Object.defineProperty(person, 'age', {value: 18,enumerable: true, // 控制属性是否可以枚举,默认值是falsewritable: true, //控制属性是否可以被修改,默认是falseconfigurable: true, //控制属性是否可以被删除,默认是false// 当有人读取person的age属性时,get函数(getter)就会被调用,且返回值就是age的值get() {console.log('有人读去了age属性');return number},// 当有人修改person的age属性时,set函数(setter)就会被调用,且收到修改的具体值set(value) {console.log('有人修改了age属性,且值是', value);number = value}})
let obj = {x: 100}let obj2 = {y: 200}Object.defineProperty(obj2, 'x', {get() {return obj.x},set(value) {obj.x = value}})
2-2 发布者订阅模式
//1.消息订阅器,内部维护了所有订阅者的列表function Dep () {this.subs = [];}Dep.prototype = {addSub: function(sub) {this.subs.push(sub);},notify: function(value) {this.subs.forEach(function(sub) {sub.update(value);});}};var dep = new Dep();//2.订阅者function Watcher() {}Watcher.prototype = {update: function(value){console.log("数据源已经变动,新的数据是"+value)}}var w1 = new Watcher();var w2 = new Watcher();dep.addSub(w1);dep.addSub(w2);//3.数据源,通过defineProperty监听数据源的变化var book = {}Object.defineProperty(book, 'name', {set: function (value) {name = value;//一旦数据源发生变化了,通知所有的订阅者更新数据dep.notify(value);},get: function () {return '《' + name + '》'}})book.name = 'vue权威指南'; // 你取了一个书名叫做vue权威指南book.name = 'vue权威指南2'; // 你取了一个书名叫做vue权威指南console.log(book.name); // 《vue权威指南》
2-3 数据绑定的实现流程
- 首先要对数据进行劫持监听,所以我们需要设置一个监听器Observer,用来监听所有属性。如果属性发上变化了,就需要告诉订阅者Watcher看是否需要更新。
- 因为订阅者是有很多个,所以我们需要有一个消息订阅器Dep来专门收集这些订阅者,然后在监听器Observer和订阅者Watcher之间进行统一管理的。
- 接着,我们还需要有一个指令解析器Compile,对每个节点元素进行扫描和解析,将相关指令对应初始化成一个订阅者Watcher,并替换模板数据或者绑定相应的函数,此时当订阅者Watcher接收到相应属性的变化,就会执行对应的更新函数,从而更新视图。
- 因此接下去我们执行以下3个步骤,实现数据的双向绑定:
- 监听器Observer,用来劫持并监听所有属性,如果有变动的,就通知所有订阅者。
- 订阅者Watcher,可以收到属性的变化通知并执行相应的函数,从而更新视图。
- 解析器Compile,可以扫描和解析每个节点的相关指令,并根据初始化模板数据以及初始化相应的订阅者

