File tree Expand file tree Collapse file tree 3 files changed +69
-2
lines changed
runtime-dom/src/components Expand file tree Collapse file tree 3 files changed +69
-2
lines changed Original file line number Diff line number Diff line change @@ -302,6 +302,8 @@ export {
302
302
normalizeStyle
303
303
} from '@vue/shared'
304
304
305
+ export { filterSingleRoot } from './componentRenderUtils'
306
+
305
307
// For test-utils
306
308
export { transformVNodeArgs } from './vnode'
307
309
Original file line number Diff line number Diff line change @@ -23,9 +23,11 @@ import {
23
23
toRaw ,
24
24
compatUtils ,
25
25
DeprecationTypes ,
26
- ComponentOptions
26
+ ComponentOptions ,
27
+ VNodeArrayChildren ,
28
+ filterSingleRoot
27
29
} from '@vue/runtime-core'
28
- import { extend } from '@vue/shared'
30
+ import { extend , PatchFlags , ShapeFlags } from '@vue/shared'
29
31
30
32
const positionMap = new WeakMap < VNode , DOMRect > ( )
31
33
const newPositionMap = new WeakMap < VNode , DOMRect > ( )
@@ -111,6 +113,28 @@ const TransitionGroupImpl: ComponentOptions = {
111
113
}
112
114
113
115
prevChildren = children
116
+
117
+ // In dev mode, comments are preserved, and it's possible for a template
118
+ // to have comments alongside the root element which makes it a fragment.
119
+ // In that case we re-assign `el` so DOM operations access the actual
120
+ // root element instead of the fragment root. (#6745)
121
+ if ( __DEV__ && prevChildren ) {
122
+ prevChildren . forEach ( child => {
123
+ if (
124
+ child . shapeFlag & ShapeFlags . COMPONENT &&
125
+ child . component &&
126
+ child . component . subTree . patchFlag & PatchFlags . DEV_ROOT_FRAGMENT
127
+ ) {
128
+ const elementRoot = filterSingleRoot (
129
+ child . component . subTree . children as VNodeArrayChildren
130
+ )
131
+ if ( elementRoot ) {
132
+ child . el = elementRoot . el
133
+ }
134
+ }
135
+ } )
136
+ }
137
+
114
138
children = slots . default ? getTransitionRawChildren ( slots . default ( ) ) : [ ]
115
139
116
140
for ( let i = 0 ; i < children . length ; i ++ ) {
Original file line number Diff line number Diff line change @@ -508,4 +508,45 @@ describe('e2e: TransitionGroup', () => {
508
508
509
509
expect ( `<TransitionGroup> children must be keyed` ) . toHaveBeenWarned ( )
510
510
} )
511
+
512
+ test (
513
+ 'works when child component has single root + comments' ,
514
+ async ( ) => {
515
+ const onErrorSpy = jest . fn ( )
516
+ await page ( ) . exposeFunction ( 'onErrorSpy' , onErrorSpy )
517
+
518
+ await page ( ) . evaluate ( ( ) => {
519
+ const { onErrorSpy } = window as any
520
+ const { createApp, ref, onErrorCaptured } = ( window as any ) . Vue
521
+
522
+ const app = createApp ( {
523
+ template : `
524
+ <div id="container">
525
+ <transition-group>
526
+ <a-component v-if="show"></a-component>
527
+ </transition-group>
528
+ </div>
529
+ <button id="toggleBtn" @click="click">button</button>
530
+ ` ,
531
+ setup : ( ) => {
532
+ onErrorCaptured ( ( ) => onErrorSpy ( ) )
533
+ const show = ref ( true )
534
+ const click = ( ) => ( show . value = false )
535
+ return { show, click }
536
+ }
537
+ } )
538
+ app . component ( 'a-component' , { template : `<!----><div></div>` } )
539
+ app . mount ( '#app' )
540
+ } )
541
+
542
+ expect ( await html ( '#container' ) ) . toBe ( '<!----><div></div>' )
543
+
544
+ await htmlWhenTransitionStart ( )
545
+ await transitionFinish ( )
546
+
547
+ expect ( onErrorSpy ) . not . toBeCalled ( )
548
+ expect ( await html ( '#container' ) ) . toBe ( '' )
549
+ } ,
550
+ E2E_TIMEOUT
551
+ )
511
552
} )
You can’t perform that action at this time.
0 commit comments