实现 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.tslet activeEffectlet 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() }