Skip to content

Commit

Permalink
fix(runtime-core): fix Transition for components with root-level v-if (
Browse files Browse the repository at this point in the history
  • Loading branch information
AlexVagrant authored Jun 4, 2024
1 parent 29425df commit ef2e737
Show file tree
Hide file tree
Showing 2 changed files with 84 additions and 1 deletion.
8 changes: 7 additions & 1 deletion packages/runtime-core/src/components/BaseTransition.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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`,

Expand Down Expand Up @@ -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,
Expand Down
77 changes: 77 additions & 0 deletions packages/vue/__tests__/e2e/Transition.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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',
Expand Down

0 comments on commit ef2e737

Please sign in to comment.