current position:Home>Reactiveeffect principle of vue3

Reactiveeffect principle of vue3

2022-06-24 09:21:23yibucuo

  1. perform setupRenderEffect
  2. The statement componentUpdateFn
  3. produce componentUpdateFn Corresponding side effect function
  4. new ReactiveEffect(), Produced activeEffect example
  5. First execution componentUpdateFn, This internal process is not attached patch
  6. patch When ,activeEffect and Responsive data Two way collection dependency
  7. When responsive data changes , Trigger associated activeEffect perform effect.schedule
  8. schedule In fact, that is () => queueJob(instance.update)
  9. queueJob take instance.update Put in queue queue in , And further execute queueFlush
  10. queueFlush Set up a Promise Micro task
  11. Wait until the micro task is executed , Batch execution instance.update
  12. Second execution componentUpdateFn, This time, the internal operation is completed by mounting patch
const effect = (instance.effect = new ReactiveEffect(
   componentUpdateFn,
   () => queueJob(instance.update), //  In fact, that is effect.run
   instance.scope
))
const update = ( instance.update = effect.run.bind(effect) ) // bind Is to return run Functional , Not execution run function 
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()

copyright notice
author[yibucuo],Please bring the original link to reprint, thank you.
https://en.cdmana.com/2022/175/202206240801439463.html

Random recommended