scheduler
单元测试
实现
结语
使用effect时可以选择性传入一些配置项,拿传入scheduler<调度>配置项举例,后续可选配置项决定着effect执不执行fn,当传入scheduler时后续就不会去直接执行fn了
scheduler
配合单元测试会有更好更理想的效果,所以先搞个单元测试
需求
-
通过 effect 的第二个参数给定的一个 scheduler 的 fn
-
effect 第一次执行的时候依旧执行fn
-
当响应式对象 set update 的时候不会执行 fn ,而是执行 scheduler
-
如果当执行 runner 的时候,会再次执行 fn
单元测试
it('scheduler', () => {
// 通过 effect 的第二个参数给定的一个 scheduler 的 fn
// effect 第一次执行的时候依旧执行fn
// 当响应式对象 set update 的时候不会执行 fn ,而是执行 scheduler
// 如果当执行 runner 的时候,会再次执行 fn
let dunmmy
let run: any
const scheduler = jest.fn(() => {
run = runner
})
const obj = reactive({ foo: 1 })
const runner = effect(
() => {
dunmmy = obj.foo
},
{
scheduler
}
)
expect(scheduler).not.toHaveBeenCalled()
expect(dunmmy).toBe(1)
obj.foo++
expect(scheduler).toHaveBeenCalledTimes(1)
expect(dunmmy).toBe(1)
run()
expect(dunmmy).toBe(2)
})
实现
class ReactiveEffect {
private _fn: any
constructor(fn, public scheduler) {
this._fn = fn
}
run() {
// 全局变量收集effect fn
activeEffect = this
return this._fn()
}
}
export function trigger(target, key) {
let depsMap = targetMap.get(target)
let dep = depsMap.get(key)
for (const effect of dep) {
if (effect.scheduler) {
effect.scheduler()
} else {
effect.run()
}
}
}
// 全局变量收集effect fn
let activeEffect
export function effect(fn, options: any = {}) { // 这里不给默认和类型会报错
// fn
const _effect = new ReactiveEffect(fn, options.scheduler)
_effect.run()
return _effect.run.bind(_effect)
}
结语
options还有很多配置项,只挑最核心的内容来复现