const bucket = new WeakMap();
let activeEffect = null;
const effectStack = [];
//封装收集副作用函数
function track(target,key){
if(!activeEffect){
return target[key]
}
//取出与target绑定的map
let depsMap = bucket.get(target);
if(!depsMap){
bucket.set(target, (depsMap = new Map()));
}
//取出与key对应的副作用函数
let depsEffets = depsMap.get(key);
if(!depsEffets){
depsMap.set(key, (depsEffets = new Set()));
}
depsEffets.add(activeEffect);
activeEffect.deps.push(depsEffets)
}
//封装触发副作用函数
function trigger(target, key){
const depsMap = bucket.get(target);
if(!depsMap){
return
}
const depsEffets = depsMap.get(key);
const effectsToRun = new Set();
depsEffets.forEach(effectfn=>{
if(effectfn!==activeEffect){
effectsToRun.add(effectfn)
}
})
effectsToRun&&effectsToRun.forEach(fn=>{
if(fn.option.scheduler){
fn.option.scheduler(fn)
}else{
fn()
}
});
}
function reactive(data){
const obj = new Proxy(data, {
get(target, key){
track(target, key);
return target[key];
},
set(target, key, value){
target[key] = value;
trigger(target,key,value);
return true;
}
})
return obj;
}
const cleanup = (effectFn) => {
for(let i=0;i<effectFn.deps.length; i++){
const deps = effectFn.deps[i];
deps.delete(effectFn)
}
effectFn.deps.length = 0;
}
const effect = (fn, option={})=>{
const effectFn = () => {
cleanup(effectFn)
activeEffect = effectFn;
effectStack.push(activeEffect);
const res = fn();
effectStack.pop();
activeEffect = effectStack[effectStack.length-1];
return res;
}
effectFn.option = option;
effectFn.deps = []
if(!option.lazy){
effectFn();
}
return effectFn;
};
const obj1 = reactive({name: "李翔", ok:true, age: 18, height: 180})
const computed = (getter)=>{
let dirty=true;
let cache = '';
const effectFn = effect(getter,{
lazy:true,
scheduler(){
dirty=true;
}
}
)
const obj = {
get value(){
if(dirty){
console.log('执行副作用函数')
value = effectFn();
dirty=false;
}
return value;
}
}
return obj;
}
const data = computed(()=>obj1.age+obj1.height)
console.log(data.value)
console.log(data.value)
obj1.age = 20;
effect(()=>{
console.log(data.value)
})
console