@@ -15,7 +15,7 @@ import { warn } from '../warning'
1515import { isKeepAlive } from './KeepAlive'
1616import { toRaw } from '@vue/reactivity'
1717import { callWithAsyncErrorHandling , ErrorCodes } from '../errorHandling'
18- import { ShapeFlags } from '@vue/shared'
18+ import { ShapeFlags , PatchFlags } from '@vue/shared'
1919import { onBeforeUnmount , onMounted } from '../apiLifecycle'
2020import { RendererElement } from '../renderer'
2121
@@ -427,21 +427,29 @@ export function getTransitionRawChildren(
427427 keepComment : boolean = false
428428) : VNode [ ] {
429429 let ret : VNode [ ] = [ ]
430+ let keyedFragmentCount = 0
430431 for ( let i = 0 ; i < children . length ; i ++ ) {
431432 const child = children [ i ]
432433 // handle fragment children case, e.g. v-for
433434 if ( child . type === Fragment ) {
435+ if ( child . patchFlag & PatchFlags . KEYED_FRAGMENT ) keyedFragmentCount ++
434436 ret = ret . concat (
435437 getTransitionRawChildren ( child . children as VNode [ ] , keepComment )
436438 )
437439 }
438440 // comment placeholders should be skipped, e.g. v-if
439- else if (
440- child . type !== Comment ||
441- ( child . type === Comment && keepComment )
442- ) {
441+ else if ( keepComment || child . type !== Comment ) {
443442 ret . push ( child )
444443 }
445444 }
445+ // #1126 if a transition children list contains multiple sub fragments, these
446+ // fragments will be merged into a flat children array. Since each v-for
447+ // fragment may contain different static bindings inside, we need to de-top
448+ // these children to force full diffs to ensure correct behavior.
449+ if ( keyedFragmentCount > 1 ) {
450+ for ( let i = 0 ; i < ret . length ; i ++ ) {
451+ ret [ i ] . patchFlag = PatchFlags . BAIL
452+ }
453+ }
446454 return ret
447455}
0 commit comments