track依赖收集(4)

track方法接受三个参数,第一个参数是收集的对象target,第二个参数是依赖操作类别type,共有三个get、has、iterate,第三个是对象属性方法key
track方法体如下
1.满足可追踪shouldTrack为true和当前副作用activeEffect存在才会进行依赖收集
2.满足1后,获取对象全局映射,如果对象全局映射不存在,则创建关于对象的全局映射,映射到的类型Map类型
3.接着第2步,获取对象target中关于key值的映射,如果不存在则创建key值的映射,映射到的类型是Set类型,上面挂有w和n属性,w指的是已经收集依赖,n指的是新的收集依赖
4.调用trackEffects方法进行依赖收集

export let shouldTrack = true
// 条件1
if (shouldTrack && activeEffect) {
    let depsMap = targetMap.get(target)
    // 条件2
    if (!depsMap) {
      targetMap.set(target, (depsMap = new Map()))
    }
    let dep = depsMap.get(key)
     // 条件3
    if (!dep) {
      depsMap.set(key, (dep = createDep()))
    }

    const eventInfo = __DEV__
      ? { effect: activeEffect, target, type, key }
      : undefined

    trackEffects(dep, eventInfo)
  }
}

trackEffects方法体如下
在介绍之前,先了解一下几个变量
effectTrackDepth:表示递归嵌套执行effect函数的深度,初始值0
trackOpBit:表示标识依赖收集的状态,初始值1
maxMarkerBits:表示最大标记的位数,值为30(文后讲述为什么)
1.先判断当前effect嵌套的深度,如果小于30层的,则继续判断当前dep是否已经是新的依赖,如果不是,key值的映射对象dep上的n设置为依赖收集状态trackOpBit,如果当前dep之前没有没存旧的依赖,则可追踪shouldTrack设置为true,反之为false;如果大于30层,可追踪shouldTrack则根据dep身上有没有存在当前副作用来取值,不存在则可追踪依赖,不在则相反
2.如果可追踪shouldTrack为true,这把当前副作用activeEffect加到key值映射对象dep中作为依赖。当前副作用activeEffect上的deps收集当前映射对象dep作为依赖

export function trackEffects(
  dep: Dep,
  debuggerEventExtraInfo?: DebuggerEventExtraInfo
) {
  let shouldTrack = false
  if (effectTrackDepth <= maxMarkerBits) {
    if (!newTracked(dep)) {
      dep.n |= trackOpBit // set newly tracked
      shouldTrack = !wasTracked(dep)
    }
  } else {
    // Full cleanup mode.
    shouldTrack = !dep.has(activeEffect!)
  }

  if (shouldTrack) {
    dep.add(activeEffect!)
    activeEffect!.deps.push(dep)
    if (__DEV__ && activeEffect!.onTrack) {
      activeEffect!.onTrack({
        effect: activeEffect!,
        ...debuggerEventExtraInfo!
      })
    }
  }
}
export const wasTracked = (dep: Dep): boolean => (dep.w & trackOpBit) > 0
export const newTracked = (dep: Dep): boolean => (dep.n & trackOpBit) > 0

现在,依赖已经收集完毕。那么接下来我们谈一下为什么maxMarkerBits最大是30。
V8针对整数有两种表示法,一种是smi,针对31位有符号范围内的整型数字(存储是32位,其中一位是符号位),另一种是HeapObject(代表这内存的实体地址)。V8对smi启用一个特殊优化,当使用smi内的数字时,引擎不需要为其专门的内存实体,并会启动快速整型操作。因此,maxMarkerBits最高取值为31位最合适,超过就对性能有影响。
那现在为什么最大为30呢,看看这个trackOpBit = 1 << ++effectTrackDepth应该差不多明白了

现在依赖已经收集了,那派发的呢?下文我们将进一步速览!
本人菜鸡,有问题望前辈及时指出,不胜感激!!

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容