美文网首页
effect 的 stop

effect 的 stop

作者: sweetBoy_9126 | 来源:发表于2024-03-16 13:58 被阅读0次
  1. stop
  • effect.spec.ts
    核心调用 stop 的时候把对应的dep里的fn 删掉
  it("stop", () => {
    let dummy
    const obj = reactive({prop: 1})
    const runner = effect(() => {
      dummy = obj.prop
    })
    obj.prop = 2
    expect(dummy).toBe(2)
    stop(runner)
    obj.prop = 3
    expect(dummy).toBe(2)
    runner()
    expect(dummy).toBe(3)
  })
  • effect.ts
class ReactiveEffect {
  ...
+  deps: any = []
+  stop() {
+    this.deps.forEach(dep => {
+     dep.delete(this)
+   }) 
+  }
}
export function track(target, key) {
  ...
+  activeEffect.deps.push(dep)  
}
export function effect(fn, options: any = {}) {
  const _effect = new ReactiveEffect(fn, options.scheduler)
 _effect.run()
 const runner: any = _effect.run.bind(_effect)
+ runner.effect = _effect
 return runner
}
+export function stop(runner) {
+  runner.effect.stop()
+}
  1. onStop
  • effect.sepc.ts
  it("onStop", () => {
    const obj = reactive({
      foo: 1
    })
    const onStop = jest.fn()
    let dummy
    const runner = effect(() => {
      dummy = obj.foo
    }, {
      onStop
    })
    stop(runner)
    expect(onStop).toBeCalledTimes(1)
  })
  • effect.ts
class ReactiveEffect {
  
  onStop?: () => void
  stop() {
    if (this.active) {
      cleanupEffect(this)
      if (this.onStop) {
        this.onStop()
      }
      this.active = false
    }
  }
}
export function effect(fn, options: any = {}) {
  const _effect: any = new ReactiveEffect(fn, options.scheduler)
  _effect.onStop = options.onStop
  ...
}
  1. 优化
    之前的代码里
  it("stop", () => {
    let dummy
    const obj = reactive({prop: 1})
    const runner = effect(() => {
      dummy = obj.prop
    })
    obj.prop = 2
    expect(dummy).toBe(2)
    stop(runner)
    // obj.prop = 3
    obj.prop++
    expect(dummy).toBe(2)
    runner()
    expect(dummy).toBe(3)
  })

我如果把 obj.prop = 3换成 obj.prop++ 的话单测就会报错

原因:
obj.prop = 3 是直接 set

obj.prop++ 实际上就是 obj.prop = obj.prop + 1 既有 get 又有 set,而触发 get 又重新收集了依赖

let shouldTrack
export function track(target, key) {
  ...
  if(!activeEffect) return
+  if (!shouldTrack) return
  ...
}

  run() {
    // 是 stop
+    if (!this.active) {
+      return this._fn()
+    }
    // 不是 stop
+    shouldTrack = true
    // 把实例对象赋值给 activeEffect
+    activeEffect = this
+    const result = this._fn()
+    shouldTrack = false
+    return result
  }

相关文章

网友评论

      本文标题:effect 的 stop

      本文链接:https://www.haomeiwen.com/subject/jpetmdtx.html