「mini-vue3」实现 effect 返回 runner

184 阅读2分钟

开启掘金成长之旅!这是我参与「掘金日新计划 · 2 月更文挑战」的第 10 天,点击查看活动详情

背景

本文记录笔者实现 mini-vue3 项目中 effect函数 返回 runner函数 的功能。

思路

书接上回 「mini-vue3」实现 reactive & effect 的「收集依赖/触发依赖」功能,我们已经实现了一个基本的 effect 模块,接下来添加一点功能,同样地,我们用测试驱动开发的思路来做,编写测试如下:

  1. effect 函数接收一个 fn 函数,首次执行 effect 时,执行一次 fn
  2. 执行 effect 会返回一个 runner 函数,执行 runner 时,再次执行 fn
  3. 执行 runner 后,返回 fn 的返回值。

编写代码

编写测试用例

effect.spec.ts 中通过 it 增加测试用例:

查看 jest 中 it 的用法

describe('effect', () => {
    // ...
    it('should return runner when call effect', () => {
        let foo = 10;
        // effect 函数接收一个 fn 函数
        const runner = effect(() => {
          foo++;
          return 'runner';
        })
        // 测试1: 首次执行 effect 时,执行一次 fn。
        expect(foo).toBe(11);
        const r = runner();
        // 测试2: 执行 runner 时,再次执行 fn。
        expect(foo).toBe(12);
        // 测试3: 执行 runner 后,返回 fn 的返回值。
        expect(r).toBe('runner');
    })
}

测试驱动开发

根据测试用例来编写项目代码,在 effect.ts 中,先让 effect 函数返回一个 runner 函数,这个 runner 函数要能执行 fn,其实就是 ReactiveEffect 里的 run 方法。

由于 run 方法里使用了 this,所以这里返回函数前要把 _effect 绑定到 this 上。

export function effect(fn: Function) {
  const _effect = new ReactiveEffect(fn);
  _effect.run();
  // 执行 effect 会返回一个 runner 函数,执行 runner 时,再次执行 fn。
  return _effect.run.bind(_effect);
}

执行 runner 后要返回 fn 的返回值,所以修改如下:

// ...
class ReactiveEffect {
  private _fn: Function;

  constructor(fn: Function) {
    this._fn = fn;
  }

  // runner 函数
  public run(): void {
    if (!this._fn) return;
    activeEffect = this;
    // 执行 runner 后,返回 fn 的返回值。
    return this._fn();
  }
}
// ....

通过 jest 执行测试

执行 yarn test effect,测试本文新增用例 should return runner when call effect,结果如下:

i2.png

可以看到,测试通过 ✅,功能已实现 🎉

总结

本文实现 effect函数 返回 runner函数 的功能,本步骤完整代码可在笔者的远程库 ---- mini-vue3: 执行 effect 返回 runner 函数 中查看。