- 执行
setupRenderEffect
- 声明了
componentUpdateFn
- 产生
componentUpdateFn
对应的副作用函数 new ReactiveEffect()
,产生了activeEffect 实例- 第一次执行
componentUpdateFn
,本次内部走的是未挂载流程patch
patch
时候,activeEffect
和 响应式数据
双向收集依赖- 当响应式数据发生变化时,触发关联的
activeEffect
执行effect.schedule
schedule
其实就是() => queueJob(instance.update)
queueJob
将instance.update
放入队列queue
中 ,且进一步执行queueFlush
queueFlush
建立了一个Promise
微任务- 等到执行微任务时候,就是批量执行
instance.update
- 第二次执行
componentUpdateFn
,本次内部走的是挂载完成的patch
const effect = (instance.effect = new ReactiveEffect(
componentUpdateFn,
() => queueJob(instance.update),
instance.scope
))
const update = ( instance.update = effect.run.bind(effect) )
class ReactiveEffect{
active = true
deps: Dep[] = []
parent: ReactiveEffect | undefined = undefined
computed?: ComputedRefImpl<T>
allowRecurse?: boolean
onStop?: () => void
onTrack?: (event: DebuggerEvent) => void
onTrigger?: (event: DebuggerEvent) => void
constructor(
public fn: () => T,
public scheduler: EffectScheduler | null = null,
scope?: EffectScope
) {
recordEffectScope(this, scope)
}
run() {
if (!this.active) {
return this.fn()
}
let parent: ReactiveEffect | undefined = activeEffect
let lastShouldTrack = shouldTrack
while (parent) {
if (parent === this) {
return
}
parent = parent.parent
}
try {
this.parent = activeEffect
activeEffect = this
shouldTrack = true
trackOpBit = 1 << ++effectTrackDepth
if (effectTrackDepth <= maxMarkerBits) {
initDepMarkers(this)
} else {
cleanupEffect(this)
}
return this.fn()
} finally {
if (effectTrackDepth <= maxMarkerBits) {
finalizeDepMarkers(this)
}
trackOpBit = 1 << --effectTrackDepth
activeEffect = this.parent
shouldTrack = lastShouldTrack
this.parent = undefined
}
}
stop() {
if (this.active) {
cleanupEffect(this)
if (this.onStop) {
this.onStop()
}
this.active = false
}
}
}
function queueJob(job) {
if (
(!queue.length ||
!queue.includes(
job,
isFlushing && job.allowRecurse ? flushIndex + 1 : flushIndex
)) &&
job !== currentPreFlushParentJob
) {
if (job.id == null) {
queue.push(job)
} else {
queue.splice(findInsertionIndex(job.id), 0, job)
}
queueFlush()
}
}
function queueFlush() {
if (!isFlushing && !isFlushPending) {
isFlushPending = true
currentFlushPromise = resolvedPromise.then(flushJobs)
}
}
const resolvedPromise = Promise.resolve()