返回

从0构建你的专属小Vue框架之升级响应式系统(上)

前端

在上一篇文章中,我们已经搭建了一个基本的渲染器模块和响应式模块。接下来,我们将对响应式模块进行升级,使其更加强大和可靠。同时,我们也将引入单元测试,以确保代码的质量和稳定性。

单元测试

在开始对响应式模块进行升级之前,我们先来建立单元测试。单元测试可以帮助我们确保代码的正确性和可靠性,并使我们能够更容易地对代码进行重构和维护。

我们可以使用 Jest 来编写单元测试。Jest 是一个流行的 JavaScript 测试框架,它简单易用,而且提供了丰富的测试功能。

首先,我们需要在项目中安装 Jest:

npm install --save-dev jest

然后,我们需要创建一个 Jest 配置文件。我们可以将它命名为 jest.config.js

module.exports = {
  preset: 'ts-jest',
  testEnvironment: 'node',
};

接下来,我们需要创建一个测试文件。我们可以将它命名为 reactive.test.js

import { reactive } from '../src/reactive';

describe('reactive', () => {
  it('should make a property reactive', () => {
    const obj = { foo: 1 };
    const reactiveObj = reactive(obj);

    expect(reactiveObj.foo).toBe(1);

    obj.foo = 2;

    expect(reactiveObj.foo).toBe(2);
  });
});

这个测试用例测试了 reactive 函数是否能够正确地将一个对象中的属性变成响应式的。

我们可以通过运行以下命令来运行测试:

npm test

如果测试通过,那么我们会看到以下输出:

PASS  src/reactive.test.js
  reactive
    ✓ should make a property reactive (1ms)

Test Suites: 1 passed, 1 total
Tests:       1 passed, 1 total
Snapshots:   0 total
Time:        0.348s
Ran all test suites.

升级响应式模块

现在,我们已经建立了单元测试,就可以开始升级响应式模块了。

首先,我们需要对响应式模块进行一些重构。我们将把响应式模块拆分成两个部分:reactive 函数和 effect 函数。reactive 函数负责将一个对象中的属性变成响应式的,而 effect 函数负责收集依赖关系并更新视图。

我们将 reactive 函数的实现改为如下:

export function reactive(obj) {
  const observed = new Map();

  return new Proxy(obj, {
    get(target, key) {
      if (!observed.has(key)) {
        observed.set(key, new Set());
      }

      observed.get(key).add(effect);

      return target[key];
    },
    set(target, key, value) {
      target[key] = value;

      observed.get(key).forEach(effect);

      return true;
    },
  });
}

我们将 effect 函数的实现改为如下:

export function effect(fn) {
  const effect = () => {
    activeEffect = effect;
    fn();
    activeEffect = null;
  };

  effect.deps = new Set();

  effect();

  return effect;
}

现在,我们已经将响应式模块升级完毕了。新的响应式模块更加健壮和完善,并且支持了单元测试。

在下一篇文章中,我们将继续对渲染器模块进行升级,使其更加强大和灵活。