Skip to content

Commit

Permalink
feat(transition): support transition to teleport component child
Browse files Browse the repository at this point in the history
  • Loading branch information
yangchangtao committed Sep 18, 2024
1 parent 9a36f2a commit 000c04f
Show file tree
Hide file tree
Showing 3 changed files with 89 additions and 5 deletions.
7 changes: 4 additions & 3 deletions packages/runtime-core/src/componentRenderUtils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ import {
warnDeprecation,
} from './compat/compatConfig'
import { shallowReadonly } from '@vue/reactivity'
import { setTransitionHooks } from './components/BaseTransition'
import { getInnerChild, setTransitionHooks } from './components/BaseTransition'

/**
* dev only flag to track whether $attrs was used during render.
Expand Down Expand Up @@ -248,13 +248,14 @@ export function renderComponentRoot(
}
// inherit transition data
if (vnode.transition) {
if (__DEV__ && !isElementRoot(root)) {
const child = getInnerChild(root) ?? root
if (__DEV__ && !isElementRoot(child)) {
warn(
`Component inside <Transition> renders non-element root node ` +
`that cannot be animated.`,
)
}
setTransitionHooks(root, vnode.transition)
setTransitionHooks(child, vnode.transition)
}

if (__DEV__ && setRoot) {
Expand Down
2 changes: 1 addition & 1 deletion packages/runtime-core/src/components/BaseTransition.ts
Original file line number Diff line number Diff line change
Expand Up @@ -484,7 +484,7 @@ function emptyPlaceholder(vnode: VNode): VNode | undefined {
}
}

function getInnerChild(vnode: VNode): VNode | undefined {
export function getInnerChild(vnode: VNode): VNode | undefined {
if (!isKeepAlive(vnode)) {
if (isTeleport(vnode.type) && vnode.children) {
return findNonCommentChild(vnode.children as VNode[])
Expand Down
85 changes: 84 additions & 1 deletion packages/vue/__tests__/e2e/Transition.spec.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { E2E_TIMEOUT, setupPuppeteer } from './e2eUtils'
import path from 'node:path'
import { Transition, createApp, h, nextTick, ref } from 'vue'
import { Teleport, Transition, createApp, h, nextTick, ref } from 'vue'

describe('e2e: Transition', () => {
const { page, html, classList, isVisible, timeout, nextFrame, click } =
Expand Down Expand Up @@ -2310,6 +2310,89 @@ describe('e2e: Transition', () => {
)
},
E2E_TIMEOUT,
),
test(
'apply transition to teleport component child',
async () => {
await page().evaluate(() => {
const { createApp, ref, h } = (window as any).Vue
createApp({
template: `
<div id="target"></div>
<div id="container">
<transition>
<Comp v-if="toggle" >content</Comp>
</transition>
</div>
<button id="toggleBtn" @click="click">button</button>
`,
components: {
Comp: {
setup() {
return () => h(Teleport, { to: '#target' }, [h('div', { class: 'test' }, 'content')])
},
},
},
setup: () => {
const toggle = ref(false)
const click = () => (toggle.value = !toggle.value)
return { toggle, click }
},
}).mount('#app')
})

expect(await html('#target')).toBe('')
expect(await html('#container')).toBe(
'<!--v-if-->',
)

const classWhenTransitionStart = () =>
page().evaluate(() => {
;(document.querySelector('#toggleBtn') as any)!.click()
return Promise.resolve().then(() => {
// find the class of teleported node
return document
.querySelector('#target div')!
.className.split(/\s+/g)
})
})

// enter
expect(await classWhenTransitionStart()).toStrictEqual([
'test',
'v-enter-from',
'v-enter-active',
])
await nextFrame()
expect(await classList('.test')).toStrictEqual([
'test',
'v-enter-active',
'v-enter-to',
])
await transitionFinish()
expect(await html('#target')).toBe(
'<div class="test">content</div>',
)

// leave
expect(await classWhenTransitionStart()).toStrictEqual([
'test',
'v-leave-from',
'v-leave-active',
])
await nextFrame()
expect(await classList('.test')).toStrictEqual([
'test',
'v-leave-active',
'v-leave-to',
])
await transitionFinish()
expect(await html('#target')).toBe('')
expect(await html('#container')).toBe(
'<!--v-if-->',
)
},
E2E_TIMEOUT,
)
})

Expand Down

0 comments on commit 000c04f

Please sign in to comment.