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?拜拜!