effect函数速览(7)

effect我们重点关注ReactiveEffect构造函数。以下速览effect函数
1.判断传入的方法是不是effect方法,如果是,获取到对应的原方法

if ((fn as ReactiveEffectRunner).effect) {
    fn = (fn as ReactiveEffectRunner).effect.fn
  }

2.创建ReactiveEffect实例化对象_effect

  const _effect = new ReactiveEffect(fn)

3.参数options如果存在则把它拓展到_effect对象上

  if (options) {
    extend(_effect, options)
    if (options.scope) recordEffectScope(_effect, options.scope)
  }

4.参数options不存在或者options.lazy不存在,则执行副作用函数

  if (!options || !options.lazy) {
    _effect.run()
  }

5.构造副作用控制器runner 并返回

const runner = _effect.run.bind(_effect) as ReactiveEffectRunner
  runner.effect = _effect
  return runner

ReactiveEffect构造函数主要介绍run和stop方法
run方法体如下
1.保存当前副作用到parent属性中,让当前副作用activeEffect为this,是否可追踪shouldTrack为true

      this.parent = activeEffect
      activeEffect = this
      shouldTrack = true

2.依赖嵌套深度和标识依赖收集的状态左位移1,判断当前嵌套深度,小于30,则设置当前对象所有依赖w属性对应层级为标识依赖收集的状态trachOpBit,大于30,则清空所有依赖。然后执行方法。

      trackOpBit = 1 << ++effectTrackDepth
      if (effectTrackDepth <= maxMarkerBits) {
        initDepMarkers(this)
      } else {
        cleanupEffect(this)
      }
      return this.fn()
export const initDepMarkers = ({ deps }: ReactiveEffect) => {
  if (deps.length) {
    for (let i = 0; i < deps.length; i++) {
      deps[i].w |= trackOpBit // set was tracked
    }
  }
}

3.最后。如果递归层级小于30,此时如果每一依赖w属性存在,n属性不存在,则把依赖从依赖数组中删除(清除掉无效依赖),清空每一依赖当前层级状态。

      if (effectTrackDepth <= maxMarkerBits) {
        finalizeDepMarkers(this)
      }
export const finalizeDepMarkers = (effect: ReactiveEffect) => {
  const { deps } = effect
  if (deps.length) {
    let ptr = 0
    for (let i = 0; i < deps.length; i++) {
      const dep = deps[i]
      if (wasTracked(dep) && !newTracked(dep)) {
        dep.delete(effect)
      } else {
        deps[ptr++] = dep
      }
      // clear bits
      dep.w &= ~trackOpBit
      dep.n &= ~trackOpBit
    }
    deps.length = ptr
  }
}

4.依赖嵌套深度和标识依赖收集的状态右位移1,当前依赖恢复为之前储存的parent属性(上一依赖),parent属性置空为null,shouldTrack恢复到上次状态

      trackOpBit = 1 << --effectTrackDepth
      activeEffect = this.parent
      shouldTrack = lastShouldTrack
      this.parent = undefined

5.如果deferStop存在,则执行函数stop方法

 if (this.deferStop) {
        this.stop()
      }

stop方法体如下:
1.如果this是当前运行的副作用函数,设置deferStop为true
2.如果当前副作用active属性为true(激活),则清除当前副作用函数上的所有依赖,如果onStop方法存在为true,则执行onStop方法,设置active属性为false

// stopped while running itself - defer the cleanup
    if (activeEffect === this) {
      this.deferStop = true
    } else if (this.active) {
      cleanupEffect(this)
      if (this.onStop) {
        this.onStop()
      }
      this.active = false
    }
function cleanupEffect(effect: ReactiveEffect) {
  const { deps } = effect
  if (deps.length) {
    for (let i = 0; i < deps.length; i++) {
      deps[i].delete(effect)
    }
    deps.length = 0
  }
}

到此,整个reactive最基础的框架基本介绍完整,ref和computed实现都是一样的,后文不再介绍(主要是懒)。这几篇文章主要是为以后如果自己忘记了,能有个地方快速拾起记忆,当然通过阅读记录能让我了解到现在还流行看源码吗QAQ?拜拜!

©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

友情链接更多精彩内容