直接上vue3的schedule单测
// effect.spect.ts
describe("effect", () => {
it("scheduler", () => {
let dummy;
let run: any;
const scheduler = jest.fn(() => {
run = runner;
});
const obj = reactive({ foo: 1 });
const runner = effect(
() => {
dummy = obj.foo;
},
{ scheduler }
);
// 初始化不执行 scheduler
expect(scheduler).not.toHaveBeenCalled();
// 初始化执行 fn
expect(dummy).toBe(1);
obj.foo++;
// 触发 reactive trigger 执行 scheduler
expect(scheduler).toHaveBeenCalledTimes(1);
// 触发 reactive trigger 不执行 fn
expect(dummy).toBe(1);
// 执行 runner,再次执行 fn
run();
expect(dummy).toBe(2);
})
})
由上面的单测可知
- 初始化不执行 scheduler
- 只有在 reactive 对象触发 set 操作的时候才执行 scheduler
- 当 effect 存在 scheduler 参数时,trigger 不再执行 fn
实现代码
// effect.ts
class ReactiveEffect {
private _fn;
// scheduler? 表示参数可传,也可以不传
constructor(fn, public scheduler?) {
this._fn = fn;
}
run() {
activeEffect = this;
this._fn();
}
}
export function trigger(target, key) {
let depsMap = targetMap.get(target);
let dep = depsMap.get(key);
for(let effect of dep) {
// effect 存在 scheduler 执行 scheduler,否则执行 fn
if(effect.scheduler) {
effect.scheduler();
} else {
effect.run();
}
}
}
export function effct(fn, options: any = {}) {
const _effect = new ReactiveEffect(fn, options.scheduler)
_effect.run();
return _effect.run.bind(_effect);
}