diff --git a/packages/runtime-core/src/components/BaseTransition.ts b/packages/runtime-core/src/components/BaseTransition.ts index cb628bf655a..0c4e53feada 100644 --- a/packages/runtime-core/src/components/BaseTransition.ts +++ b/packages/runtime-core/src/components/BaseTransition.ts @@ -464,10 +464,14 @@ export function getTransitionRawChildren( 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) - ) + if (child.patchFlag & PatchFlags.STABLE_FRAGMENT && child.key != null) { + ret.push(child) + } else { + 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 (keepComment || child.type !== Comment) { diff --git a/packages/vue/__tests__/TransitionGroup.spec.ts b/packages/vue/__tests__/TransitionGroup.spec.ts index 6ba05763801..9112e2f5b98 100644 --- a/packages/vue/__tests__/TransitionGroup.spec.ts +++ b/packages/vue/__tests__/TransitionGroup.spec.ts @@ -508,4 +508,20 @@ describe('e2e: TransitionGroup', () => { expect(` children must be keyed`).toHaveBeenWarned() }) + + test('should not warn v-for + template', () => { + createApp({ + template: ` + + + + `, + setup: () => { + const items = ref(['a', 'b', 'c']) + return { items } + } + }).mount(document.createElement('div')) + + expect(` children must be keyed`).not.toHaveBeenWarned() + }) })