读了第四章里的调度讲解,在此记录理解
所谓可调度,指的是当 trigger 动作触发副作用函数重新执行时,有能力决定副作用函数执行的时机、次数以及方式。
决定调度时机的执行
const data = {foo:1}
const bucket = new WeakMap()
let activeEffect;
const effectStack = []
function effect(fn,options={}){
const effectFn = ()=>{
cleanup(effectFn)
activeEffect = effectFn;
effectStack.push(effectFn)
fn()
// 当副作用函数执行完毕后,将当前副作用函数弹出栈,并把activeEffect还原之前的值
effectStack.pop()
activeEffect = effectStack[effectStack.length-1]
}
// 将options挂载到effectFn函数上
effectFn.options = options
effectFn.deps=[]
effectFn()
}
function cleanup(effectFn){
for(let i=0;i<effectFn.deps.length;i++){
effectFn.deps[i].delete(effectFn)
}
effectFn.deps.length = 0
}
function track(target,key){
if(!activeEffect) return
let depsMap = bucket.get(target)
if(!depsMap){bucket.set(target,depsMap=new Map())}
let deps = depsMap.get(key)
if(!deps){depsMap.set(key,deps=new Set())}
deps.add(activeEffect)
activeEffect.deps.push(deps)
}
function trigger(target,key){
let depsMap = bucket.get(target)
if(!depsMap) return
const effects=depsMap.get(key)
const effectsToRun = new Set()
effects && effects.forEach(effectFn=>{
if(effectFn!==activeEffect){
effectsToRun.add(effectFn)
}
})
console.error(effectsToRun)
effectsToRun.forEach(effectFn=>{
if(effectFn.options.scheduler){
// 如果有调度函数,则执行调度函数
effectFn.options.scheduler(effectFn)
}else{
effectFn()
}
})
}
const obj = new Proxy(data,{
get(target,key){
track(target,key)
return target[key]
},
set(target,key,newVal){
target[key] = newVal
trigger(target,key)
}
})
effect(
function effectFn1(){
console.log(obj.foo)
},
// options
{
scheduler(fn){
// 将副作用函数放到宏任务队列中执行
setTimeout(fn)
}
}
)
obj.foo++
console.log('结束了')
没有调度时正常打印顺序是:1,2,结束了
网友评论