@@ -164,7 +164,9 @@ const BaseTransitionImpl: ComponentOptions = {
164164 if (
165165 __DEV__ &&
166166 mode &&
167- mode !== 'in-out' && mode !== 'out-in' && mode !== 'default'
167+ mode !== 'in-out' &&
168+ mode !== 'out-in' &&
169+ mode !== 'default'
168170 ) {
169171 warn ( `invalid <transition> mode: ${ mode } ` )
170172 }
@@ -460,22 +462,28 @@ export function setTransitionHooks(vnode: VNode, hooks: TransitionHooks) {
460462
461463export function getTransitionRawChildren (
462464 children : VNode [ ] ,
463- keepComment : boolean = false
465+ keepComment : boolean = false ,
466+ parentKey ?: VNode [ 'key' ]
464467) : VNode [ ] {
465468 let ret : VNode [ ] = [ ]
466469 let keyedFragmentCount = 0
467470 for ( let i = 0 ; i < children . length ; i ++ ) {
468- const child = children [ i ]
471+ let child = children [ i ]
472+ // #5360 inherit parent key in case of <template v-for>
473+ const key =
474+ parentKey == null
475+ ? child . key
476+ : String ( parentKey ) + String ( child . key != null ? child . key : i )
469477 // handle fragment children case, e.g. v-for
470478 if ( child . type === Fragment ) {
471479 if ( child . patchFlag & PatchFlags . KEYED_FRAGMENT ) keyedFragmentCount ++
472480 ret = ret . concat (
473- getTransitionRawChildren ( child . children as VNode [ ] , keepComment )
481+ getTransitionRawChildren ( child . children as VNode [ ] , keepComment , key )
474482 )
475483 }
476484 // comment placeholders should be skipped, e.g. v-if
477485 else if ( keepComment || child . type !== Comment ) {
478- ret . push ( child )
486+ ret . push ( key != null ? cloneVNode ( child , { key } ) : child )
479487 }
480488 }
481489 // #1126 if a transition children list contains multiple sub fragments, these
0 commit comments