参考文档
一、页面—>数据
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 = 18
let person = {
name: "张三",
sex: '男',
}
Object.defineProperty(person, 'age', {
value: 18,
enumerable: true, // 控制属性是否可以枚举,默认值是false
writable: true, //控制属性是否可以被修改,默认是false
configurable: 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,可以扫描和解析每个节点的相关指令,并根据初始化模板数据以及初始化相应的订阅者