Effect
上一节,我们已经完成reactive
的基本逻辑,这一节,我们来创建一个effect
,为后面的依赖收集和触发依赖做准备。
单测
下面,就跟着单测一起来了解effect
的功能点。
// src/reactivity/test/effect.spec.ts
import {effect} from "../effect"
import {reactive} from "../reactive"
describe("effect", () => {
it("happy path", () => {
// 创建一个响应式对象
const user = reactive({
age: 10
})
// 定义全局变量nextAge
let nextAge;
// 执行effect,接收一个fn作为参数,在函数内部对nextAge进行赋值
effect(() => {
nextAge = user.age + 1
})
// 赋值成功,说明在执行effect的时候会自动执行传入的函数
expect(nextAge).toBe(11)
})
})
同reactive
一样,effect
也是一个函数,默认接收一个fn
作为参数,从单例可以看出当执行effect(fn)
的时候,默认会执行里面的fn
,这一节,我们就来完成这个简单的功能,至于怎么做到数据同步更改,等我们完成收集依赖
和触发依赖
。
编码
在这里有一点跟reactive
不同,effect模块我们不仅仅是导出一个effect
函数,还需要一个公共的类ReactiveEffect
,当然你也可以用构造函数来代替它的功能。
// src/reactivity/effect.ts
let activeEffect;
class ReactiveEffect {
private _fn: any
constructor (fn) {
this._fn = fn
}
public run () {
activeEffect = this //将当前实例对象赋值给全局变量activeEffect,在依赖收集的时候有用
this._fn()
}
}
export function effect (fn) {
const _effect = new ReactiveEffect(fn)
_effect.run()
}
上面便是我们这一节要完成的所有代码及功能,看起来很简单,但是却有点不大好理解,为什么要这么写?可以把effect
当成一个纽带,当然它更像vue2
中的watcher
。
测试结果
执行yarn test
PS D:\user\desktop\mini-vue> yarn test
yarn run v1.22.10
$ jest
PASS src/reactivity/tests/effect.spec.ts
PASS src/reactivity/tests/index.spec.ts
PASS src/reactivity/tests/reactive.spec.ts
Test Suites: 3 passed, 3 total
Tests: 3 passed, 3 total
Snapshots: 0 total
Time: 1.075 s
Ran all test suites.
Done in 2.59s.
可以看到我们之前写的3个测试文件都已经通过。
总结
这节课,我们完成了effect
的主要功能,通过effect(fn)
返回一个用ReactiveEffect
包裹的实例对象,当执行函数的时候会自动调用内部的run
方法,实际上也就是通过effect
传入的fn
。
下一节,我们将一起来实现依赖收集和触发依赖。