美文网首页
vue.js设计与实现(四)-响应系统-调度执行-时机

vue.js设计与实现(四)-响应系统-调度执行-时机

作者: 幸宇 | 来源:发表于2023-01-08 15:53 被阅读0次

    读了第四章里的调度讲解,在此记录理解

    所谓可调度,指的是当 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,结束了

    调度后打印:

    image.png

    相关文章

      网友评论

          本文标题:vue.js设计与实现(四)-响应系统-调度执行-时机

          本文链接:https://www.haomeiwen.com/subject/lcpucdtx.html