实现 effect 的 scheduler 功能

scheduler 负责调度 Vue3 中的任务:类似于一个管家,对家中大小事情的收集

单测

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
//reactivity/__test__/effect.spec.ts
...
it('scheduler', () => {
/**
* 1. 通过effect 的第二个参数给定一个 scheduler的fn
* 2. effect 第一次执行的时候 还会执行 fn
* 3. 当 响应式对象 修改更新 的时候不会执行 fn 而是执行 scheduler
* 4. 如果说当执行 runner 的时候,会再次执行 fn
*/
let dummy
let run: any
const scheduler = jest.fn(() => {
run = runner
})
const obj = reactive({ foo: 1 })
const runner = effect(
() => {
dummy = obj.foo
},
{ scheduler }
)
expect(scheduler).not.toHaveBeenCalled()
expect(dummy).toBe(1)
obj.foo++
expect(scheduler).toHaveBeenCalledTimes(1)
expect(dummy).toBe(1)
run()
expect(dummy).toBe(2)
})

实现单测

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
//reactivity/effect.ts
...
class ReactiveEffect {
private _fn: any //私有变量
public scheduler: Function | undefined
constructor(fn, scheduler?: Function) {
//新增
this._fn = fn
}
run() {
activeEffect = this
this._fn()
}
}
export const trigger = (target, key) => {
let depsMap = targetMap.get(target)
let dep = depsMap.get(key)
for (const effect of dep) {
//新增判断scheduler
if (effect.scheduler) {
effect.scheduler()
} else {
effect.run()
}
}
}
export const effect = (fn, options: any = {}) => {
const { scheduler } = options
const _effect = new ReactiveEffect(fn, scheduler) //新增
_effect.run()
const runner = _effect.run.bind(_effect)
return runner
}