diff --git a/packages/compiler-ssr/__tests__/ssrTransitionGroup.spec.ts b/packages/compiler-ssr/__tests__/ssrTransitionGroup.spec.ts
index 82122e621c7..4ca320b78b5 100644
--- a/packages/compiler-ssr/__tests__/ssrTransitionGroup.spec.ts
+++ b/packages/compiler-ssr/__tests__/ssrTransitionGroup.spec.ts
@@ -11,11 +11,18 @@ describe('transition-group', () => {
"const { ssrRenderList: _ssrRenderList } = require("vue/server-renderer")
return function ssrRender(_ctx, _push, _parent, _attrs) {
+ const _tag = (_attrs && typeof _attrs.tag === 'string') ? _attrs.tag : ''
+ if (_tag) {
+ _push(\`<\${_tag}>\`)
+ }
_push(\`\`)
_ssrRenderList(_ctx.list, (i) => {
_push(\`
\`)
})
_push(\`\`)
+ if (_tag) {
+ _push(\`\${_tag}>\`)
+ }
}"
`)
})
@@ -114,6 +121,10 @@ describe('transition-group', () => {
"const { ssrRenderList: _ssrRenderList } = require("vue/server-renderer")
return function ssrRender(_ctx, _push, _parent, _attrs) {
+ const _tag = (_attrs && typeof _attrs.tag === 'string') ? _attrs.tag : ''
+ if (_tag) {
+ _push(\`<\${_tag}>\`)
+ }
_push(\`\`)
_ssrRenderList(10, (i) => {
_push(\`\`)
@@ -125,6 +136,9 @@ describe('transition-group', () => {
_push(\`ok
\`)
}
_push(\`\`)
+ if (_tag) {
+ _push(\`\${_tag}>\`)
+ }
}"
`)
})
diff --git a/packages/compiler-ssr/src/ssrCodegenTransform.ts b/packages/compiler-ssr/src/ssrCodegenTransform.ts
index 536cbb5c1e9..0d09887317f 100644
--- a/packages/compiler-ssr/src/ssrCodegenTransform.ts
+++ b/packages/compiler-ssr/src/ssrCodegenTransform.ts
@@ -4,6 +4,7 @@ import {
type CompilerError,
type CompilerOptions,
ElementTypes,
+ type ExpressionNode,
type IfStatement,
type JSChildNode,
NodeTypes,
@@ -84,7 +85,7 @@ export interface SSRTransformContext {
onError: (error: CompilerError) => void
helper(name: T): T
pushStringPart(part: TemplateLiteral['elements'][0]): void
- pushStatement(statement: IfStatement | CallExpression): void
+ pushStatement(statement: IfStatement | CallExpression | ExpressionNode): void
}
function createSSRTransformContext(
diff --git a/packages/compiler-ssr/src/transforms/ssrTransformTransitionGroup.ts b/packages/compiler-ssr/src/transforms/ssrTransformTransitionGroup.ts
index 27ddebec103..831dffb8393 100644
--- a/packages/compiler-ssr/src/transforms/ssrTransformTransitionGroup.ts
+++ b/packages/compiler-ssr/src/transforms/ssrTransformTransitionGroup.ts
@@ -6,7 +6,10 @@ import {
NodeTypes,
type TransformContext,
buildProps,
+ createBlockStatement,
createCallExpression,
+ createIfStatement,
+ createSimpleExpression,
findProp,
} from '@vue/compiler-dom'
import { SSR_RENDER_ATTRS } from '../runtimeHelpers'
@@ -112,7 +115,38 @@ export function ssrProcessTransitionGroup(
context.pushStringPart(`${tag.value!.content}>`)
}
} else {
+ // _attrs may contain tag property
+ const hasFallthroughAttrs = node.props.some(
+ p =>
+ p.type === NodeTypes.DIRECTIVE &&
+ p.name === 'bind' &&
+ p.exp &&
+ p.exp.type === NodeTypes.SIMPLE_EXPRESSION &&
+ p.exp.content === '_attrs',
+ )
+ if (hasFallthroughAttrs) {
+ context.pushStatement(
+ createSimpleExpression(
+ `const _tag = (_attrs && typeof _attrs.tag === 'string') ? _attrs.tag : ''`,
+ ),
+ )
+ context.pushStatement(
+ createIfStatement(
+ createSimpleExpression('_tag'),
+ createBlockStatement([createSimpleExpression('_push(`<${_tag}>`)')]),
+ ),
+ )
+ }
// fragment
processChildren(node, context, true, true, true)
+
+ if (hasFallthroughAttrs) {
+ context.pushStatement(
+ createIfStatement(
+ createSimpleExpression('_tag'),
+ createBlockStatement([createSimpleExpression('_push(`${_tag}>`)')]),
+ ),
+ )
+ }
}
}
diff --git a/packages/server-renderer/__tests__/ssrAttrFallthrough.spec.ts b/packages/server-renderer/__tests__/ssrAttrFallthrough.spec.ts
index e8cfa75e77c..66f6688b7f3 100644
--- a/packages/server-renderer/__tests__/ssrAttrFallthrough.spec.ts
+++ b/packages/server-renderer/__tests__/ssrAttrFallthrough.spec.ts
@@ -75,4 +75,20 @@ describe('ssr: attr fallthrough', () => {
``,
)
})
+
+ // #12827
+ test('with transition-group tag name', async () => {
+ expect(
+ await renderToString(
+ createApp({
+ components: {
+ one: {
+ template: ``,
+ },
+ },
+ template: `{{i}}
`,
+ }),
+ ),
+ ).toBe(``)
+ })
})