runner
TIP
本篇笔记对应的分支号为: main分支:8fcd786
在动手实现之前,我们需要先弄清楚两个问题:runner
是什么 以及 runner
实现了什么功能。
runner
是什么 🤔
还记得上一节在实现 依赖收集
以及 依赖触发
时的 effect
方法么?
runner
就是effect
的返回的一个函数
。
runner
实现了什么功能 🤔
runner
主要做了两件事情:
- 执行
runner
时,会再次执行传入effect
中的方法,我们暂且叫它fn
;runner
会返回fn
执行后的结果。
runner
实现 依据上面的描述,我们先来编写 runner
的测试用例:
// src/reactivity/__tests__/effect.spec.ts
it('renturn a runner when call effect', () => {
let foo = 10
const runner = effect(() => {
foo++
return 'foo'
})
// 传入 effect 的方法 fn 会被立即执行一次,所以foo = 11
expect(foo).toBe(11)
const res = runner()
// 执行 effect 返回的 runner 函数后,fn 会再次执行,所以foo = 12
expect(foo).toBe(12)
// runner 会返回 fn 的执行结果,所以 res = 'foo'
expect(res).toBe('foo')
})
接下来,我们便可以根据测试用例来对 effect
方法进行改造。我们先来看下现在的 effect
方法定义:
// src/reactivity/effect.ts
export function effect(fn) {
// 实例化 ReactiveEffect 类,并将依赖传入
const _effect = new ReactiveEffect(fn)
_effect.run()
}
现在,effect
需要返回一个 runner
函数,并且在执行 runner
函数时会再次执行传入 effect
的方法 fn
,而现在 fn
的执行是通过 ReactiveEffect
暴露出来的 run
方法实现的。所以,我们只需要将 ReactiveEffect
实例上的 run
暴露出去即可:
注意
由于 fn
被绑定在 ReactiveEffect
的实例属性 _fn
上,且 run
通过 this._fn()
的方式来调用它,所以在将 _effect.run
暴露出去的时候需要绑定 this
作用域。
// src/reactivity/effect.ts
export function effect(fn) {
// 实例化 ReactiveEffect 类,并将依赖传入
const _effect = new ReactiveEffect(fn)
_effect.run()
return _effect.run.bind(_effect)
}
现在,effect
方法已经可以返回 runner
函数了,那么我们该如何拿到 fn
的返回值呢?其实很简单,只需要改造下 ReactiveEffect
中的 run
方法,将 _fn
的执行结果返回即可:
// src/reactivity/effect.ts
class ReactiveEffect {
private _fn: any
constructor(fn) {
this._fn = fn
}
run() {
activeEffect = this
return this._fn()
}
}
至此,runner
功能就实现完成啦~
Loading...