Просмотр исходного кода

fix(runtime-vapor): invoke updated before activated on reactivation

daiwei 3 недель назад
Родитель
Сommit
5086bdc131

+ 53 - 0
packages/runtime-vapor/__tests__/vdomInterop.spec.ts

@@ -2452,6 +2452,59 @@ describe('vdomInterop', () => {
       ])
     })
 
+    test('should invoke updated before activated on reactivation', async () => {
+      const calls: string[] = []
+
+      const VaporChild = defineVaporComponent({
+        props: ['msg'],
+        setup(props: any) {
+          onActivated(() => calls.push('activated'))
+          return template('<div></div>')()
+        },
+      })
+
+      const VdomChild = defineComponent({
+        setup() {
+          return () => h('span', 'vdom')
+        },
+      })
+
+      const current = shallowRef<any>(VaporChild)
+      const msg = ref('one')
+
+      const App = defineComponent({
+        setup() {
+          return () =>
+            h(KeepAlive, null, {
+              default: () =>
+                current.value === VaporChild
+                  ? h(VaporChild as any, {
+                      msg: msg.value,
+                      onVnodeUpdated: () => calls.push('vnode updated'),
+                      onVnodeMounted: () => calls.push('vnode mounted'),
+                    })
+                  : h(VdomChild),
+            })
+        },
+      })
+
+      const root = document.createElement('div')
+      const app = createApp(App)
+      app.use(vaporInteropPlugin)
+      app.mount(root)
+      await nextTick()
+      calls.length = 0
+
+      current.value = VdomChild
+      await nextTick()
+
+      msg.value = 'two'
+      current.value = VaporChild
+      await nextTick()
+
+      expect(calls).toEqual(['vnode updated', 'activated', 'vnode mounted'])
+    })
+
     test('should expose the latest vapor root element in updated hooks on reactivation', async () => {
       const VaporChild = defineVaporComponent({
         props: {

+ 10 - 11
packages/runtime-vapor/src/vdomInterop.ts

@@ -406,8 +406,6 @@ const vaporInteropImpl: Omit<
       vnode.dirs = null
     }
     const shouldUpdate = shouldUpdateComponent(cached, vnode)
-    activate(instance, container, anchor)
-    insert(vnode.anchor as any, container, anchor)
     if (shouldUpdate) {
       instance.rawPropsRef!.value = filterReservedProps(vnode.props)
       instance.rawSlotsRef!.value = vnode.children
@@ -424,9 +422,7 @@ const vaporInteropImpl: Omit<
       if (vnode.dirs) {
         invokeDirectiveHook(vnode, cached, parentComponent, 'beforeUpdate')
       }
-    }
-    queuePostFlushCb(() => {
-      if (shouldUpdate) {
+      queuePostFlushCb(() => {
         syncVNodeRootEl(vnode, instance)
         if (vnode.dirs) {
           invokeDirectiveHook(vnode, cached, parentComponent, 'updated')
@@ -440,18 +436,21 @@ const vaporInteropImpl: Omit<
             [vnode, cached],
           )
         }
-      }
-
-      const vnodeMountedHook = vnode.props && vnode.props.onVnodeMounted
-      if (vnodeMountedHook) {
+      })
+    }
+    activate(instance, container, anchor)
+    insert(vnode.anchor as any, container, anchor)
+    const vnodeMountedHook = vnode.props && vnode.props.onVnodeMounted
+    if (vnodeMountedHook) {
+      queuePostFlushCb(() => {
         callWithAsyncErrorHandling(
           vnodeMountedHook,
           parentComponent,
           ErrorCodes.VNODE_HOOK,
           [vnode],
         )
-      }
-    })
+      })
+    }
   },
 
   deactivate(vnode, container) {