فهرست منبع

fix(runtime-vapor): flush post jobs after unmount

三咲智子 Kevin Deng 2 سال پیش
والد
کامیت
7cacb655e0

+ 16 - 9
packages/runtime-vapor/src/apiRender.ts

@@ -5,7 +5,7 @@ import {
   setCurrentInstance,
 } from './component'
 import { insert, querySelector, remove } from './dom/element'
-import { flushPostFlushCbs, queuePostRenderEffect } from './scheduler'
+import { flushPostFlushCbs, queuePostFlushCb } from './scheduler'
 import { invokeLifecycle } from './componentLifecycle'
 import { VaporLifecycleHooks } from './apiLifecycle'
 import {
@@ -107,14 +107,15 @@ function mountComponent(
   invokeLifecycle(instance, VaporLifecycleHooks.BEFORE_MOUNT, 'beforeMount')
 
   insert(instance.block!, instance.container)
-  instance.isMounted = true
-  instance.comps.forEach(comp => {
-    comp.isMounted = true
-  })
 
   // hook: mounted
-  invokeLifecycle(instance, VaporLifecycleHooks.MOUNTED, 'mounted', true)
-
+  invokeLifecycle(
+    instance,
+    VaporLifecycleHooks.MOUNTED,
+    'mounted',
+    instance => (instance.isMounted = true),
+    true,
+  )
   return instance
 }
 
@@ -128,6 +129,12 @@ export function unmountComponent(instance: ComponentInternalInstance) {
   block && remove(block, container)
 
   // hook: unmounted
-  invokeLifecycle(instance, VaporLifecycleHooks.UNMOUNTED, 'unmounted', true)
-  queuePostRenderEffect(() => (instance.isUnmounted = true))
+  invokeLifecycle(
+    instance,
+    VaporLifecycleHooks.UNMOUNTED,
+    'unmounted',
+    instance => queuePostFlushCb(() => (instance.isUnmounted = true)),
+    true,
+  )
+  flushPostFlushCbs()
 }

+ 5 - 3
packages/runtime-vapor/src/componentLifecycle.ts

@@ -1,18 +1,20 @@
 import { invokeArrayFns } from '@vue/shared'
 import type { VaporLifecycleHooks } from './apiLifecycle'
 import { type ComponentInternalInstance, setCurrentInstance } from './component'
-import { queuePostRenderEffect } from './scheduler'
+import { queuePostFlushCb } from './scheduler'
 import { type DirectiveHookName, invokeDirectiveHook } from './directives'
 
 export function invokeLifecycle(
   instance: ComponentInternalInstance,
   lifecycle: VaporLifecycleHooks,
   directive: DirectiveHookName,
+  cb?: (instance: ComponentInternalInstance) => void,
   post?: boolean,
 ) {
   invokeArrayFns(post ? [invokeSub, invokeCurrent] : [invokeCurrent, invokeSub])
 
   function invokeCurrent() {
+    cb && cb(instance)
     const hooks = instance[lifecycle]
     if (hooks) {
       const fn = () => {
@@ -20,7 +22,7 @@ export function invokeLifecycle(
         instance.scope.run(() => invokeArrayFns(hooks))
         reset()
       }
-      post ? queuePostRenderEffect(fn) : fn()
+      post ? queuePostFlushCb(fn) : fn()
     }
 
     invokeDirectiveHook(instance, directive)
@@ -28,7 +30,7 @@ export function invokeLifecycle(
 
   function invokeSub() {
     instance.comps.forEach(comp =>
-      invokeLifecycle(comp, lifecycle, directive, post),
+      invokeLifecycle(comp, lifecycle, directive, cb, post),
     )
   }
 }

+ 2 - 2
packages/runtime-vapor/src/dom/event.ts

@@ -9,7 +9,7 @@ import {
   recordEventMetadata,
 } from '../componentMetadata'
 import { withKeys, withModifiers } from '@vue/runtime-dom'
-import { queuePostRenderEffect } from '../scheduler'
+import { queuePostFlushCb } from '../scheduler'
 
 export function addEventListener(
   el: Element,
@@ -35,7 +35,7 @@ export function on(
 ) {
   const handler: DelegatedHandler = eventHandler(handlerGetter, options)
   let cleanupEvent: (() => void) | undefined
-  queuePostRenderEffect(() => {
+  queuePostFlushCb(() => {
     cleanupEvent = addEventListener(el, event, handler, options)
   })
 

+ 3 - 3
packages/runtime-vapor/src/dom/templateRef.ts

@@ -15,7 +15,7 @@ import {
   remove,
 } from '@vue/shared'
 import { warn } from '../warning'
-import { queuePostRenderEffect } from '../scheduler'
+import { queuePostFlushCb } from '../scheduler'
 
 export type NodeRef = string | Ref | ((ref: Element) => void)
 
@@ -90,10 +90,10 @@ export function setRef(el: Element, ref: NodeRef, refFor = false) {
         }
       }
       doSet.id = -1
-      queuePostRenderEffect(doSet)
+      queuePostFlushCb(doSet)
 
       onScopeDispose(() => {
-        queuePostRenderEffect(() => {
+        queuePostFlushCb(() => {
           if (isArray(existing)) {
             remove(existing, el)
           } else if (_isString) {

+ 3 - 3
packages/runtime-vapor/src/renderEffect.ts

@@ -11,7 +11,7 @@ import {
   getCurrentInstance,
   setCurrentInstance,
 } from './component'
-import { queueJob, queuePostRenderEffect } from './scheduler'
+import { queueJob, queuePostFlushCb } from './scheduler'
 import { VaporErrorCodes, callWithAsyncErrorHandling } from './errorHandling'
 import { invokeDirectiveHook } from './directives'
 
@@ -40,14 +40,14 @@ export function renderEffect(cb: () => void) {
 
       effect.run()
 
-      queuePostRenderEffect(() => {
+      queuePostFlushCb(() => {
         instance.isUpdating = false
         if (dirs) {
           invokeDirectiveHook(instance, 'updated')
         }
         // updated hook
         if (u) {
-          queuePostRenderEffect(u)
+          queuePostFlushCb(u)
         }
       })
     } else {

+ 3 - 3
packages/runtime-vapor/src/scheduler.ts

@@ -53,7 +53,7 @@ export function queueJob(job: SchedulerJob) {
   }
 }
 
-export function queuePostRenderEffect(cb: SchedulerJobs) {
+export function queuePostFlushCb(cb: SchedulerJobs) {
   if (!isArray(cb)) {
     if (!(cb.flags! & SchedulerJobFlags.QUEUED)) {
       pendingPostFlushCbs.push(cb)
@@ -216,8 +216,8 @@ export const createVaporPreScheduler: SchedulerFactory =
 export const createVaporPostScheduler: SchedulerFactory =
   instance => (job, effect, immediateFirstRun, hasCb) => {
     if (!immediateFirstRun) {
-      queuePostRenderEffect(job)
+      queuePostFlushCb(job)
     } else if (!hasCb) {
-      queuePostRenderEffect(effect.run.bind(effect))
+      queuePostFlushCb(effect.run.bind(effect))
     }
   }