单测
//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)
}