diff --git a/packages/compiler-ssr/__tests__/ssrTransitionGroup.spec.ts b/packages/compiler-ssr/__tests__/ssrTransitionGroup.spec.ts
index aee771fb3fe..2a3b6d3b4d4 100644
--- a/packages/compiler-ssr/__tests__/ssrTransitionGroup.spec.ts
+++ b/packages/compiler-ssr/__tests__/ssrTransitionGroup.spec.ts
@@ -26,10 +26,10 @@ describe('transition-group', () => {
``
).code
).toMatchInlineSnapshot(`
- "const { ssrRenderList: _ssrRenderList } = require(\\"vue/server-renderer\\")
+ "const { ssrRenderAttrs: _ssrRenderAttrs, ssrRenderList: _ssrRenderList } = require(\\"vue/server-renderer\\")
return function ssrRender(_ctx, _push, _parent, _attrs) {
- _push(\`
\`)
+ _push(\`\`)
_ssrRenderList(_ctx.list, (i) => {
_push(\`\`)
})
@@ -44,10 +44,14 @@ describe('transition-group', () => {
``
).code
).toMatchInlineSnapshot(`
- "const { ssrRenderList: _ssrRenderList } = require(\\"vue/server-renderer\\")
+ "const { ssrRenderAttrs: _ssrRenderAttrs, ssrRenderList: _ssrRenderList } = require(\\"vue/server-renderer\\")
return function ssrRender(_ctx, _push, _parent, _attrs) {
- _push(\`<\${_ctx.someTag}>\`)
+ _push(\`<\${
+ _ctx.someTag
+ }\${
+ _ssrRenderAttrs(_attrs)
+ }>\`)
_ssrRenderList(_ctx.list, (i) => {
_push(\`\`)
})
@@ -85,4 +89,23 @@ describe('transition-group', () => {
}"
`)
})
+
+ test('attribute fallthrough', () => {
+ expect(
+ compile(
+ `
+ `
+ ).code
+ ).toMatchInlineSnapshot(`
+ "const { mergeProps: _mergeProps } = require(\\"vue\\")
+ const { ssrRenderAttrs: _ssrRenderAttrs } = require(\\"vue/server-renderer\\")
+
+ return function ssrRender(_ctx, _push, _parent, _attrs) {
+ _push(\`\`)
+ }"
+ `)
+ })
})
diff --git a/packages/compiler-ssr/src/transforms/ssrTransformComponent.ts b/packages/compiler-ssr/src/transforms/ssrTransformComponent.ts
index 83d552103ca..4c3a961cd65 100644
--- a/packages/compiler-ssr/src/transforms/ssrTransformComponent.ts
+++ b/packages/compiler-ssr/src/transforms/ssrTransformComponent.ts
@@ -48,7 +48,10 @@ import {
ssrProcessSuspense,
ssrTransformSuspense
} from './ssrTransformSuspense'
-import { ssrProcessTransitionGroup } from './ssrTransformTransitionGroup'
+import {
+ ssrProcessTransitionGroup,
+ ssrTransformTransitionGroup
+} from './ssrTransformTransitionGroup'
import { isSymbol, isObject, isArray } from '@vue/shared'
import { buildSSRProps } from './ssrTransformElement'
@@ -95,7 +98,10 @@ export const ssrTransformComponent: NodeTransform = (node, context) => {
if (component === SUSPENSE) {
return ssrTransformSuspense(node, context)
}
- return // built-in component: fallthrough
+ if (component === TRANSITION_GROUP) {
+ return ssrTransformTransitionGroup(node, context)
+ }
+ return // other built-in components: fallthrough
}
// Build the fallback vnode-based branch for the component's slots.
diff --git a/packages/compiler-ssr/src/transforms/ssrTransformTransitionGroup.ts b/packages/compiler-ssr/src/transforms/ssrTransformTransitionGroup.ts
index 378c4f333d4..dedf1f64075 100644
--- a/packages/compiler-ssr/src/transforms/ssrTransformTransitionGroup.ts
+++ b/packages/compiler-ssr/src/transforms/ssrTransformTransitionGroup.ts
@@ -1,16 +1,71 @@
-import { ComponentNode, findProp, NodeTypes } from '@vue/compiler-dom'
+import {
+ AttributeNode,
+ buildProps,
+ ComponentNode,
+ createCallExpression,
+ DirectiveNode,
+ findProp,
+ JSChildNode,
+ NodeTypes,
+ TransformContext
+} from '@vue/compiler-dom'
+import { SSR_RENDER_ATTRS } from '../runtimeHelpers'
import { processChildren, SSRTransformContext } from '../ssrCodegenTransform'
+import { buildSSRProps } from './ssrTransformElement'
+const wipMap = new WeakMap()
+
+interface WIPEntry {
+ tag: AttributeNode | DirectiveNode
+ propsExp: string | JSChildNode | null
+}
+
+// phase 1: build props
+export function ssrTransformTransitionGroup(
+ node: ComponentNode,
+ context: TransformContext
+) {
+ return () => {
+ const tag = findProp(node, 'tag')
+ if (tag) {
+ const otherProps = node.props.filter(p => p !== tag)
+ const { props, directives } = buildProps(
+ node,
+ context,
+ otherProps,
+ true, /* isComponent */
+ false, /* isDynamicComponent */
+ true /* ssr (skip event listeners) */
+ )
+ let propsExp = null
+ if (props || directives.length) {
+ propsExp = createCallExpression(context.helper(SSR_RENDER_ATTRS), [
+ buildSSRProps(props, directives, context)
+ ])
+ }
+ wipMap.set(node, {
+ tag,
+ propsExp
+ })
+ }
+ }
+}
+
+// phase 2: process children
export function ssrProcessTransitionGroup(
node: ComponentNode,
context: SSRTransformContext
) {
- const tag = findProp(node, 'tag')
- if (tag) {
+ const entry = wipMap.get(node)
+ if (entry) {
+ const { tag, propsExp } = entry
if (tag.type === NodeTypes.DIRECTIVE) {
// dynamic :tag
context.pushStringPart(`<`)
context.pushStringPart(tag.exp!)
+ if (propsExp) {
+ context.pushStringPart(propsExp)
+ }
context.pushStringPart(`>`)
processChildren(
@@ -30,7 +85,11 @@ export function ssrProcessTransitionGroup(
context.pushStringPart(`>`)
} else {
// static tag
- context.pushStringPart(`<${tag.value!.content}>`)
+ context.pushStringPart(`<${tag.value!.content}`)
+ if (propsExp) {
+ context.pushStringPart(propsExp)
+ }
+ context.pushStringPart(`>`)
processChildren(node, context, false, true)
context.pushStringPart(`${tag.value!.content}>`)
}