关于前端:实现-effect-的-stop-功能

26次阅读

共计 1415 个字符,预计需要花费 4 分钟才能阅读完成。

实现 effect 的 stop 性能

//effect.spec
 it('stop', () => {
        let dummy
        const obj = reactive({prop: 1})
        const runner = effect(() => {dummy = obj.prop})
        obj.prop = 2
        expect(dummy).toBe(2)
        // stop 一个 runner 之后
        stop(runner)
        obj.prop++
        // 依赖再次更新,过后传入的 effect 则不会从新执行
        expect(dummy).toBe(2)
        // runner 不受到影响
        runner()
        expect(dummy).toBe(3)
    })
//effect.ts
let activeEffect
let shouldTrack 
const targetMap = new WeakMap()

class ReactiveEffect{
    private _fn
    deps=[]
    active= true
    constructor(fn,public scheduler?){this._fn = fn}
    run(){if (!this.active) {return this._fn();
          }
      
          // 应该收集
          shouldTrack = true;
          activeEffect = this;
          const r = this._fn();
      
          // 重置
          shouldTrack = false;
      
          return r;
    }
    stop(){if (this.active) {cleanupEffect(this)     
        }   
        this.active = false
    }
}



function cleanupEffect(effect){effect.deps.forEach((dep: any) => {dep.delete(effect)
      })
}

export function track(target, key){let depsMap = targetMap.get(target)
    if(!depsMap){depsMap = new Map()
        targetMap.set(target,depsMap)
    }
    let dep = depsMap.get(key)
    if(!dep){dep = new Set()
        depsMap.set(key,dep)
    }
    // 判断是否应该收集,stop 过的 shouldTrack 为 false
    if(activeEffect&&shouldTrack){activeEffect.deps.push(dep)
        dep.add(activeEffect)
    }   
}

export function trigger(target, key){let depsMap = targetMap.get(target)
    let deps = depsMap.get(key)
    for(const effect of deps){if(effect.scheduler){effect.scheduler()
        }else{effect.run()
        }   
    }
}

export function effect(fn,option:any={}){const _effect = new ReactiveEffect(fn,option.scheduler)
    _effect.run();
    let runner:any = _effect.run.bind(_effect)
    runner.effect = _effect

    return runner
 }

 export function stop(runner){runner.effect.stop()
 }

正文完
 0