File tree Expand file tree Collapse file tree
runtime-core/src/components Expand file tree Collapse file tree Original file line number Diff line number Diff line change @@ -10,6 +10,7 @@ import {
1010 type VNode ,
1111 type VNodeArrayChildren ,
1212 cloneVNode ,
13+ createCommentVNode ,
1314 isSameVNodeType ,
1415} from '../vnode'
1516import { warn } from '../warning'
@@ -155,11 +156,18 @@ const BaseTransitionImpl: ComponentOptions = {
155156 return ( ) => {
156157 const children =
157158 slots . default && getTransitionRawChildren ( slots . default ( ) , true )
158- if ( ! children || ! children . length ) {
159+ const child =
160+ children && children . length
161+ ? findNonCommentChild ( children )
162+ : // Keep explicit default-slot conditionals on the same transition path
163+ // as regular v-if branches, which render a comment placeholder.
164+ instance . subTree
165+ ? createCommentVNode ( )
166+ : undefined
167+ if ( ! child ) {
159168 return
160169 }
161170
162- const child : VNode = findNonCommentChild ( children )
163171 // there's no need to track reactivity for these props so use the raw
164172 // props for a bit better perf
165173 const rawProps = toRaw ( props )
Original file line number Diff line number Diff line change @@ -1428,6 +1428,57 @@ describe('e2e: Transition', () => {
14281428 } ,
14291429 E2E_TIMEOUT ,
14301430 )
1431+
1432+ // #14727
1433+ test (
1434+ 'explicit default slot template can toggle again before leave finishes' ,
1435+ async ( ) => {
1436+ const spy = vi . fn ( )
1437+ const currentPage = page ( )
1438+ currentPage . on ( 'pageerror' , spy )
1439+
1440+ await page ( ) . evaluate ( ( ) => {
1441+ const { createApp, ref } = ( window as any ) . Vue
1442+ createApp ( {
1443+ template : `
1444+ <div id="container">
1445+ <transition name="test">
1446+ <template v-if="show" #>
1447+ <div class="test">text</div>
1448+ </template>
1449+ </transition>
1450+ </div>
1451+ <button id="toggleBtn" @click="show = !show">button</button>
1452+ ` ,
1453+ setup : ( ) => {
1454+ const show = ref ( true )
1455+ return { show }
1456+ } ,
1457+ } ) . mount ( '#app' )
1458+ } )
1459+
1460+ expect ( await html ( '#container' ) ) . toBe ( '<div class="test">text</div>' )
1461+
1462+ await click ( '#toggleBtn' )
1463+ await nextTick ( )
1464+ await click ( '#toggleBtn' )
1465+
1466+ expect (
1467+ await page ( ) . $$eval ( '#container .test' , nodes =>
1468+ nodes . map ( node => node . className ) ,
1469+ ) ,
1470+ ) . toStrictEqual ( [ 'test test-enter-from test-enter-active' ] )
1471+
1472+ await nextFrame ( )
1473+ await transitionFinish ( )
1474+ await nextFrame ( )
1475+
1476+ expect ( spy ) . not . toHaveBeenCalled ( )
1477+ currentPage . off ( 'pageerror' , spy )
1478+ expect ( await html ( '#container' ) ) . toBe ( '<div class="test">text</div>' )
1479+ } ,
1480+ E2E_TIMEOUT ,
1481+ )
14311482 } )
14321483
14331484 describe ( 'transition with KeepAlive' , ( ) => {
You can’t perform that action at this time.
0 commit comments