实现 effect 的 stop 功能
//effect.spec
it('stop', () => {
let dummy
const obj = reactive({ prop: 1 })
const runner = effect(() => {
dummy = obj.prop
})
obj.prop = 2
expect(dummy).toBe(2)
// stop 一个 runner 之后
stop(runner)
obj.prop++
// 依赖再次更新,当时传入的 effect 则不会重新执行
expect(dummy).toBe(2)
// runner 不受到影响
runner()
expect(dummy).toBe(3)
})
//effect.ts
let activeEffect
let shouldTrack
const targetMap = new WeakMap()
class ReactiveEffect{
private _fn
deps=[]
active= true
constructor(fn,public scheduler?){
this._fn = fn
}
run(){
if (!this.active) {
return this._fn();
}
// 应该收集
shouldTrack = true;
activeEffect = this;
const r = this._fn();
// 重置
shouldTrack = false;
return r;
}
stop(){
if (this.active) {
cleanupEffect(this)
}
this.active = false
}
}
function cleanupEffect(effect){
effect.deps.forEach((dep: any) => {
dep.delete(effect)
})
}
export function track(target, key){
let depsMap = targetMap.get(target)
if(!depsMap){
depsMap = new Map()
targetMap.set(target,depsMap)
}
let dep = depsMap.get(key)
if(!dep){
dep = new Set()
depsMap.set(key,dep)
}
//判断是否应该收集,stop过的shouldTrack为false
if(activeEffect&&shouldTrack){
activeEffect.deps.push(dep)
dep.add(activeEffect)
}
}
export function trigger(target, key){
let depsMap = targetMap.get(target)
let deps = depsMap.get(key)
for(const effect of deps){
if(effect.scheduler){
effect.scheduler()
}else{
effect.run()
}
}
}
export function effect(fn,option:any={}){
const _effect = new ReactiveEffect(fn,option.scheduler)
_effect.run();
let runner:any = _effect.run.bind(_effect)
runner.effect = _effect
return runner
}
export function stop(runner){
runner.effect.stop()
}
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。