目标

effect(fn, { schdeuler })
effect 除了传入 fn 函数外,还能在传入 options,options 中有一个属性 scheduler 函数

  1. 通过 effect 的第二个参数对象,给定的一个属性 scheduler 的函数
  2. effect 第二次执行的时候还会执行 fn
  3. 当响应性对象 set update 不会执行 fn 而是执行 scheduler
  4. 如果当执行 runner 的时候,会再次执行 fn

    1. it('scheduler', () => {
    2. let dummy;
    3. let run: any;
    4. const scheduler = jest.fn(() => {
    5. run = runner;
    6. });
    7. const obj = reactive({ foo: 1 });
    8. const runner = effect(
    9. () => {
    10. dummy = obj.foo;
    11. },
    12. { scheduler }
    13. );
    14. expect(scheduler).not.toHaveBeenCalled();
    15. expect(dummy).toBe(1);
    16. // should be called on first trigger
    17. obj.foo++;
    18. expect(scheduler).toHaveBeenCalledTimes(1);
    19. // should not run yet
    20. expect(dummy).toBe(1);
    21. // manually run
    22. run();
    23. // should have run
    24. expect(dummy).toBe(2);
    25. });

    实现

    ```typescript class EffectReactive { private _fn; // 构造函数增加接收 scheduler?(可选的), 使用 public 关键字可使 schduler 对外暴露 constructor(fn, public scheduler?) { this._fn = fn; } run() { activeEffect = this; return this._fn(); } }

// 增加 options 对象来接收 scheduler export function effect(fn, options: any = {}) { // 把 scheduler 传入到更低层的 EffectReactive const _effect = new EffectReactive(fn, options.scheduler);

_effect.run();

return _effect.run.bind(_effect); }

export function trigger(target, key) { const depsMap = targetMap.get(target); const dep = depsMap.get(key);

for (const effect of dep) { // 判断是否有 scheduler,如果有就运行 scheduler if (effect.scheduler) { effect.scheduler(); } else { // 调用 .run 即调用 fn effect.run(); } } } ```