刚写的原理,先放上来再说,后续补充解说
obeserver.js
/*
主要是把这个对象变成get和set
*/
class Observer{
constructor(data){
//专门用于劫持用的
this.observer(data)
}
observer(data){
//要对这个data数据,将原有的属性改成set和get的形式
//首先,data要存在,并且要是对象 才能劫持,否则就不劫持,直接return掉
if(!data || typeof data !== 'object'){
return;
}
//要将数据一一劫持,先获取到data的key和value
Object.keys(data).forEach(key => {
//劫持
//定义响应式
this.defineReactive(data,key,data[key]);
this.observer(data[key]);//深度劫持,对象里的属性如果为对象,也需要劫持一下
})
}
//定义响应式,也就是给某个对象,定义某个属性
defineReactive(obj,key,value){
let that = this;
let dep = new Dep();//每个变化的数据,都会对应一个数组,这个数组是存放所有更新的操作
Object.defineProperty(obj, key, {
enumerable:true,//可枚举,就是for循环能循环出来
configurable:true,//可操作性
get(){//取值的时候,调这个方法
Dep.target && dep.addSub(Dep.target);
return value;
},
set(newValue){//赋值的时候,调这个方法,newValue就是赋值的时候的新值
if(newValue != value){
//这里的this不是当前实例,但是要用到实例下的属性
that.observer(newValue);//如果新赋值的值,是对象,那就要对新值也劫持一下,这样新值也有get和set方法了
value = newValue;
dep.notify();//通知所有人,数据更新了
}
}
})
}
}
//发布订阅
class Dep{
constructor(){
//订阅的数组
this.subs = [];
}
//添加订阅
addSub(watcher){
this.subs.push(watcher);
}
//通知
notify(){
this.subs.forEach(watcher => watcher.update())
}
}