fix(transition-group): vue 2 compatible handling of transition-group w/ multiple v-for children

fix #1126
This commit is contained in:
Evan You 2020-06-29 18:15:53 -04:00
parent d32aed0906
commit 86d3972855
2 changed files with 15 additions and 8 deletions

View File

@ -15,7 +15,7 @@ import { warn } from '../warning'
import { isKeepAlive } from './KeepAlive'
import { toRaw } from '@vue/reactivity'
import { callWithAsyncErrorHandling, ErrorCodes } from '../errorHandling'
import { ShapeFlags } from '@vue/shared'
import { ShapeFlags, PatchFlags } from '@vue/shared'
import { onBeforeUnmount, onMounted } from '../apiLifecycle'
import { RendererElement } from '../renderer'
@ -427,21 +427,29 @@ export function getTransitionRawChildren(
keepComment: boolean = false
): VNode[] {
let ret: VNode[] = []
let keyedFragmentCount = 0
for (let i = 0; i < children.length; i++) {
const child = children[i]
// handle fragment children case, e.g. v-for
if (child.type === Fragment) {
if (child.patchFlag & PatchFlags.KEYED_FRAGMENT) keyedFragmentCount++
ret = ret.concat(
getTransitionRawChildren(child.children as VNode[], keepComment)
)
}
// comment placeholders should be skipped, e.g. v-if
else if (
child.type !== Comment ||
(child.type === Comment && keepComment)
) {
else if (keepComment || child.type !== Comment) {
ret.push(child)
}
}
// #1126 if a transition children list contains multiple sub fragments, these
// fragments will be merged into a flat children array. Since each v-for
// fragment may contain different static bindings inside, we need to de-top
// these children to force full diffs to ensure correct behavior.
if (keyedFragmentCount > 1) {
for (let i = 0; i < ret.length; i++) {
ret[i].patchFlag = PatchFlags.BAIL
}
}
return ret
}

View File

@ -100,8 +100,7 @@ const TransitionGroupImpl = {
const cssTransitionProps = resolveTransitionProps(rawProps)
const tag = rawProps.tag || Fragment
prevChildren = children
const slotChildren = slots.default ? slots.default() : []
children = getTransitionRawChildren(slotChildren)
children = slots.default ? getTransitionRawChildren(slots.default()) : []
for (let i = 0; i < children.length; i++) {
const child = children[i]
@ -126,7 +125,7 @@ const TransitionGroupImpl = {
}
}
return createVNode(tag, null, slotChildren)
return createVNode(tag, null, children)
}
}
}