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(\`\`) + }" + `) + }) }) 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(``) }