fix(runtime-core): fix Transition for components with root-level v-if (#7678)

close #7649
This commit is contained in:
AlexVagrant 2024-06-04 22:06:07 +08:00 committed by GitHub
parent 29425df1ac
commit ef2e737577
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 84 additions and 1 deletions

View 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,

View 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',