Vue 中Observer、Dep、Watcher的关系图
- 使Object变为可观测的对象——通过Object.definedPrototype()为数据对象添加get和set属性,实现数据劫持;
- 那么数据在改变的时候就会通过setter通知依赖他的视图,这里我们需要先收集数据有哪些依赖,这个收集的动作是在getter中进行的;
- 收集的依赖需要一个管理器去管理他们,此时就出现了Dep类;
- 在Dep中我们有depend()收集依赖,然后有nofiy()通知对应的依赖进行更新;
- 我们为这个依赖创建Watcher实例,当外界通过Watcher获取数据的时候会触发getter,此时会将当前的Watcher实例添加到dep的subs(即存放依赖的数组)数组中;
- 当数据放生变化时,会触发setter,向Dep发送notify,然后Dep中会调用Watcher中的更新操作;
- Watcher接收到通知后,会向外界发送通知,变化通知到外界后可能会触发视图更新,也有可能触发用户的某个回调函数等。
begin
Object.defineProperty——简单例子
首先要了解一下Object.defineProperty的相关知识
Object.defineProperty()详解请戳我
var person = {
}
Object.defineProperty(person,'name',{
configurable:false,//能否使用delete、能否需改属性特性、或能否修改访问器属性、,false为不可重新定义,默认值为true
enumerable:false,//对象属性是否可通过for-in循环,flase为不可循环,默认值为true
writable:false,//对象属性是否可修改,flase为不可修改,默认值为true
value:'xiaoming' //对象属性的默认值,默认值为undefined
});
通过Object.defineProperty将一个对象转换为可以观测的示例
const cat = {
};
let alike = 'fish';
Object.defineProperty(cat, 'like', {
get() {
console.log('触发了get方法');
return alike;
},
set(val) {
alike = val;
console.log('触发了set方法');
},
});
console.log(cat.like);
cat.like = 'mouse';
console.log(cat.like);
//输出的结果如下
触发了get方法
fish
触发了set方法
触发了get方法
mouse
接下来看一下vue源码中怎么将object转化为一个可观测的object
源码路径
src/core/observer/index.js
Oberver类
- Observer类会通过递归的方式把一个对象的所有属性都转化成可观测对象