]> git.ipfire.org Git - thirdparty/vuejs/core.git/commitdiff
fix(runtime-core): fix Transition for components with root-level v-if (#7678)
authorAlexVagrant <1113629699@qq.com>
Tue, 4 Jun 2024 14:06:07 +0000 (22:06 +0800)
committerGitHub <noreply@github.com>
Tue, 4 Jun 2024 14:06:07 +0000 (22:06 +0800)
close #7649

packages/runtime-core/src/components/BaseTransition.ts
packages/vue/__tests__/e2e/Transition.spec.ts

index 070418a19a0ed3bd6c4ca723bc248ab906fbaab6..848369074ea92b07c8ca61121fc8a1871602578d 100644 (file)
@@ -135,6 +135,11 @@ export const BaseTransitionPropsValidators = {
   onAppearCancelled: TransitionHookValidator,
 }
 
+const recursiveGetSubtree = (instance: ComponentInternalInstance): VNode => {
+  const subTree = instance.subTree
+  return subTree.component ? recursiveGetSubtree(subTree.component) : subTree
+}
+
 const BaseTransitionImpl: ComponentOptions = {
   name: `BaseTransition`,
 
@@ -213,7 +218,8 @@ const BaseTransitionImpl: ComponentOptions = {
       if (
         oldInnerChild &&
         oldInnerChild.type !== Comment &&
-        !isSameVNodeType(innerChild, oldInnerChild)
+        !isSameVNodeType(innerChild, oldInnerChild) &&
+        recursiveGetSubtree(instance).type !== Comment
       ) {
         const leavingHooks = resolveTransitionHooks(
           oldInnerChild,
index 4fe78ae8ab0d7e37ccf3cdde1e900b000174a0c5..26c39a0ecc085d8a2077f98dc04ad9b554062b6f 100644 (file)
@@ -1215,6 +1215,83 @@ describe('e2e: Transition', () => {
       E2E_TIMEOUT,
     )
 
+    // issue https://github.com/vuejs/core/issues/7649
+    test(
+      'transition with v-if at component root-level',
+      async () => {
+        await page().evaluate(() => {
+          const { createApp, ref } = (window as any).Vue
+          createApp({
+            template: `
+              <div id="container">
+                <transition name="test" mode="out-in">
+                  <component class="test" :is="view"></component>
+                </transition>
+              </div>
+              <button id="toggleBtn" @click="click">button</button>
+              <button id="changeViewBtn" @click="change">button</button>
+            `,
+            components: {
+              one: {
+                template: '<div v-if="false">one</div>',
+              },
+              two: {
+                template: '<div>two</div>',
+              },
+            },
+            setup: () => {
+              const toggle = ref(true)
+              const view = ref('one')
+              const click = () => (toggle.value = !toggle.value)
+              const change = () =>
+                (view.value = view.value === 'one' ? 'two' : 'one')
+              return { toggle, click, change, view }
+            },
+          }).mount('#app')
+        })
+        expect(await html('#container')).toBe('<!--v-if-->')
+
+        // change view -> 'two'
+        await page().evaluate(() => {
+          ;(document.querySelector('#changeViewBtn') as any)!.click()
+        })
+        // enter
+        expect(await classWhenTransitionStart()).toStrictEqual([
+          'test',
+          'test-enter-from',
+          'test-enter-active',
+        ])
+        await nextFrame()
+        expect(await classList('.test')).toStrictEqual([
+          'test',
+          'test-enter-active',
+          'test-enter-to',
+        ])
+        await transitionFinish()
+        expect(await html('#container')).toBe('<div class="test">two</div>')
+
+        // change view -> 'one'
+        await page().evaluate(() => {
+          ;(document.querySelector('#changeViewBtn') as any)!.click()
+        })
+        // leave
+        expect(await classWhenTransitionStart()).toStrictEqual([
+          'test',
+          'test-leave-from',
+          'test-leave-active',
+        ])
+        await nextFrame()
+        expect(await classList('.test')).toStrictEqual([
+          'test',
+          'test-leave-active',
+          'test-leave-to',
+        ])
+        await transitionFinish()
+        expect(await html('#container')).toBe('<!--v-if-->')
+      },
+      E2E_TIMEOUT,
+    )
+
     // #3716
     test(
       'wrapping transition + fallthrough attrs',