在我们给effect函数传入fn函数的同时也可以传入一些配置项,这里拿scheduler以及onStop来举个例子
scheduler
scheduler(调度),我们函数的执行需要调度控制,它就相当于一个开关,来把控是否要执行fn,当我们传入了scheduler时,就不会去执行fn了,我们先来写个单元测试,来把理想的功能写一下
这里当我们obj.foo++时会触发effect函数执行,但是我们传入了scheduler,所以fn不会再走了,而是去执行scheduler ,因此dummy = obj.foo这里的逻辑走不了,所以dummy的值不会更新
我们来改动一下effect, 这里为什么要用Object.assign()为依赖项绑定options呢,因为我们再执行依赖性的时候要根据options上的属性来控制,所以当trigger时,我们会检查一下options选项,所以要给_effect绑定好options
export function effect(fn, options: any = {}) {
const _effect = new reactiveEffect(fn, options.schdeuler)
// extend(_effect, options)
Object.assign(_effect, options)
_effect.run()
const runner: any = _effect.run.bind(_effect)
runner._effect = _effect
return runner
}
class reactiveEffect {
private _fn: any
//用于将那个依赖存进去
deps = []
active = true
constructor(fn, public schduler?: Function) {
this._fn = fn
this.schduler = schduler
}
run() {
activeEffect = this
return this._fn()
}
stop() {
if (this.active) {
this.active = false
//这里存放的dep是set结构,所以需要delete来操作
clearEffect(this)
}
}
}
export function trigger(target, key) {
const depMap = targetMap.get(target)
const deps = depMap.get(key)
for (const dep of deps) {
if (dep.scheduler) {
dep.scheduler()
} else {
dep.run()
}
}
}
这样当我们有scheduler时,在依赖触发时就会调用scheduler而不是fn了,所以就实现了控制fn的调用
onStop
onStop是stop之后的回调函数,stop上节我们有讲到过, 调用stop之后我们依赖性会被清空,同时也不会再收集依赖, 这样就监听不了reactive对象的变化了,onStop也就是stop之后的回调,因此我们在stop函数中调用即可
class reactiveEffect {
private _fn: any
//用于将那个依赖存进去
deps = []
active = true
onStop?: () => void
constructor(fn, public schduler?: Function) {
this._fn = fn
this.schduler = schduler
}
run() {
activeEffect = this
return this._fn()
}
stop() {
if (this.active) {
this.active = false
//这里存放的dep是set结构,所以需要delete来操作
clearEffect(this)
if (this.onStop) {
this.onStop()
}
}
}
}
到此就已经实现了scheduler以及onStop的功能了
写在最后
options其实还有很多配置项,这里挑最核心的内容来复现,直接看本篇章可能有些吃力,希望这次的博客工程能像连续剧一样让大家看得津津有味。