const arrayProto=Array.prototype;
const arrayMenthods=Object.create(arrayProto);
['push','pop','shift','unshift','unshift','splice','sort','reverse'].forEach(function(method) {
const original=arrayProto[method];
Object.defineProperty(arrayMenthods,method,{
value: function mutator(...args) {
const ob=this.__ob__;
ob.dep.notify();
// return original.apply(this,args);
return result;
},
enumerable: false,
writable: true,
configurable: true
})
});
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();
}
}
}
//__proto__是否 可用
const hasProto='__proto__' in {};
const arrayKeys=Object.getOwnPropertyNames(arrayMenthods);
//工具函数
function def(obj,key,val,enumerable){
Object.defineProperty(obj,key,{
value:val,
enumerable:!enumerable,
writable:true,
configurable:true
})
}
//拦截器
class Observer {
constructor(value) {
this.value=value;
this.dep=new Dep();
def(value,'__ob__',this)
if(Array.isArray(value)) {
// value.__proto__=arrayMenthods;
const augment=hasProto? protoAugment:copyAugment;
augment(value,arrayMenthods,arrayKeys)
}
else {
this.walk(value);
}
}
}
/**
尝试为value创建一个Observer实例
如果创建成果,直接返回创建的Observer实例
如果value已经存在一个Observer实例,则直接返回
**/
function observe(value,asRootData){
if(!isObject(value)){
return;
}
let ob;
if(hasOwn(value,'__ob__')&&value.__ob__ instanceof Observer){
ob=value.__ob__;
}
else{
ob=new Observer(value);
}
return ob;
}
function defineReactive(data,key,val) {
let childOb=observe(val);
let dep=new Dep();//修改
Object.defineProperty(data,key,{
enumerable: true,
configurable: true,
get: function(t) {
console.log("get",window.target)
// dep.push(window.target)
dep.depend();
//新增
if(childOb){
childOb.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();
}
});
};
function protoAugment(target,src,keys) {
target.__proto__=src;
}
function copyAugment(target,src,keys) {
for(let i=0,l=keys.length;i<l;i++) {
const key=keys[i];
def(target,key,src[key]);
}
}
console