const bucket = new WeakMap();
let activeEffect = null;
function track(target, key){
if(!activeEffect) return;
let depsMap = bucket.get(target);
if(!depsMap){
bucket.set(target, depsMap=new Map())
}
let depsEffect = depsMap.get(key);
if(!depsEffect){
depsMap.set(key, depsEffect=new Set())
}
depsEffect.add(activeEffect);
activeEffect.deps.push(depsEffect);
}
function trigger(target, key){
const depsMap = bucket.get(target)
if(!depsMap) return;
const depsEffect = depsMap.get(key);
if(!depsEffect) return;
let effectsToRun = new Set();
depsEffect.forEach(effect=>{
if(effect!==activeEffect){
effectsToRun.add(effect)
}
})
effectsToRun.forEach(effect=>{
if(effect.option.scheduler){
effect.option.scheduler(effect)
}else{
effect();
}
})
}
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);
return true;
}
})
return obj
}
function cleanup(effectFn){
for(let i=0;i<effectFn.deps.length;i++){
const deps = effectFn.deps[i]; //是一个set类型的数据
deps.delete(effectFn);
}
effectFn.deps.length = 0;
}
const effectStack = [];
function registerEffect (fn, option={}) {
function effectFn(){
activeEffect=effectFn;
effectStack.push(activeEffect);
cleanup(effectFn);
const res = fn()
effectStack.pop();
activeEffect = effectStack[effectStack.length-1];
return res
}
effectFn.deps = [];
effectFn.option = option;
if(!option.lazy){
effectFn();
}
return effectFn;
}
const data = {
name: '李翔',
age: 18,
ok: true
}
const obj = reactive(data);
const jobQueue = new Set();
const p = Promise.resolve();
let isFlushing = false;
function flushJob() {
if(isFlushing) return;
isFlushing = true;
p.then(()=>{
jobQueue.forEach(job=>job())
}).finally(()=>{
isFlushing = false;
})
}
// registerEffect(()=>{
// console.log('执行effect1')
// registerEffect(()=>{
// console.log('执行effect2')
// obj.age
// })
// obj.name
// }, {
// scheduler(fn){
// setTimeout(()=>{
// fn()
// }, 1000)
// }
// })
// obj.name = "dora"
// obj.age = 20
// registerEffect(()=>{
// console.log(obj.age)
// }, {
// scheduler(fn){
// jobQueue.add(fn);
// flushJob();
// }
// })
// obj.age++
// obj.age++
// obj.age++
// obj.age++
function computed(getter){
let dirty = true;
let value;
const effectFn = registerEffect(getter, {
lazy: true,
scheduler(){
trigger(obj, 'value')
dirty = true;
}
})
const obj = {
get value(){
if(dirty){
value = effectFn();
dirty = false;
}
track(obj, 'value')
return value;
},
}
return obj;
}
const computedData = computed(()=>obj.age+10)
console.log(computedData.value)
obj.age++
console.log(computedData.value)
console