console
class Dep{
constructor(){
this.subs=[];
}
addSub(sub){
this.subs.push(sub)
}
removeSub(sub){
remove(this.subs,sub)
}
depend(){
if(window.target){
this.addSub(window.target);
}
}
notify(){
const subs=this.subs.slice();
console.log("subs",subs)
for(let i=0,l=subs.length;i<l;i++){
subs[i].update();
}
}
}
function remove(arr,item){
if(arr.length){
const index=arr.indexOf(item);
if(index>-1){
return arr.slice(index,1);
}
}
}
function defineReactive(data,key,val){
let dep=new Dep();
Object.defineProperty(data,key,{
enumerable:true,
configurable:true,
get:function(t){
console.log("get",window.target)
dep.depend();
return val;
},
set:function(newVal){
console.log("set",newVal)
if(val===newVal){
return;
}
for(let i=0;i<dep.length;i++){
dep[i](newVal,val);
}
val=newVal;
dep.notify();
}
});
};
const bailRE=/[^\w.$]/;
function parsePath(path){
if(bailRE.test(path)){
return;
}
const segments=path.split(".");
return function(obj){
for(let i=0;i<segments.length;i++){
if(!obj){
return;
}
obj=obj[segments[i]];
};
return obj;
}
};
class Watcher{
constructor(vm,expOrFn,cb){
this.vm=vm;
this.getter=parsePath(expOrFn);
console.log("this.getter",this.getter,typeof this.getter)
this.cb=cb;
this.value=this.get();
}
get(){
window.target=this;
console.log("window.target",window.target,this.getter)
let value=this.getter.call(this.vm,this.vm);
window.target=undefined;
return value;
}
update() {
const oldValue=this.value;
this.value=this.get();
this.cb.call(this.vm,this.value,oldValue);
}
}
let obj={};
let vm= defineReactive(obj,"z",100);
new Watcher(obj,"z",function(oldv,newV){
console.log("==watch==",oldv,newV)
})
console.log(obj,obj.z)
请看javascript