单测

//effect.spec.ts
it('scheduler', () => {
        // 1. scheduler 作为 effect 的一个 option
        // 2. 有了 scheduler 之后原来的 fn 参数只会执行初始化的一次
        // 3. 如果依赖更新时不会执行 fn ,而是会去执行 scheduler
        // 4. runner 不受影响
        let dummy
        let run: any
        const scheduler = jest.fn(() => {
            run = runner
        })
        const obj = reactive({ foo: 1 })
        // 在这里将 scheduler 作为一个 option 传入 effect
        const runner = effect(
            () => {
                dummy = obj.foo
            },
            { scheduler }
        )
        expect(scheduler).not.toHaveBeenCalled()
        // 会执行一次 effect 传入的 fn
        expect(dummy).toBe(1)
        obj.foo++
        // 有了 scheduler 之后,原来的 fn 就不会执行了
        expect(scheduler).toHaveBeenCalledTimes(1)
        expect(dummy).toBe(1)
        run()
        expect(dummy).toBe(2)
    })
//effect.ts
class ReactiveEffect{
    private _fn
    constructor(fn,public scheduler?){
        this._fn = fn
    }
    run(){
        activeEffect = this
        let res =this._fn()
        return res
    }
}

let activeEffect
const targetMap = new WeakMap()
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)
    }
    dep.add(activeEffect)
}

export function trigger(target, key){
    let depsMap = targetMap.get(target)
    let deps = depsMap.get(key)
    for(const effect of deps){
        //在修改值的时候,有scheduler先执行scheduler
        if(effect.scheduler){
            effect.scheduler()
        }else{
            effect.run()
        }   
    }
}

export function effect(fn,option:any={}){
    //讲option.scheduler传入参数
    const _effect = new ReactiveEffect(fn,option.scheduler)
    _effect.run()
    return _effect.run.bind(_effect)
 }

ohoherror
21 声望1 粉丝