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应该差不多明白了
现在依赖已经收集了,那派发的呢?下文我们将进一步速览!
本人菜鸡,有问题望前辈及时指出,不胜感激!!