diff --git a/packages/compiler-ssr/__tests__/ssrVShow.spec.ts b/packages/compiler-ssr/__tests__/ssrVShow.spec.ts
index d0f3ec93036..bf8fd6090a2 100644
--- a/packages/compiler-ssr/__tests__/ssrVShow.spec.ts
+++ b/packages/compiler-ssr/__tests__/ssrVShow.spec.ts
@@ -33,6 +33,44 @@ describe('ssr: v-show', () => {
`)
})
+ test('with component', () => {
+ expect(
+ compileWithWrapper(``).code,
+ ).toMatchInlineSnapshot(`
+ "const { resolveComponent: _resolveComponent } = require("vue")
+ const { ssrRenderComponent: _ssrRenderComponent, ssrRenderAttrs: _ssrRenderAttrs } = require("vue/server-renderer")
+
+ return function ssrRender(_ctx, _push, _parent, _attrs) {
+ const _component_Foo = _resolveComponent("Foo")
+
+ _push(\`
\`)
+ _push(_ssrRenderComponent(_component_Foo, { style: {color:'red'} }, null, _parent, undefined, {
+ style: (_ctx.foo) ? null : { display: "none" }
+ }))
+ _push(\`
\`)
+ }"
+ `)
+ })
+
+ test('with dynamic component', () => {
+ expect(
+ compileWithWrapper(
+ ``,
+ ).code,
+ ).toMatchInlineSnapshot(`
+ "const { resolveDynamicComponent: _resolveDynamicComponent, createVNode: _createVNode } = require("vue")
+ const { ssrRenderVNode: _ssrRenderVNode, ssrRenderAttrs: _ssrRenderAttrs } = require("vue/server-renderer")
+
+ return function ssrRender(_ctx, _push, _parent, _attrs) {
+ _push(\`\`)
+ _ssrRenderVNode(_push, _createVNode(_resolveDynamicComponent("Foo"), { style: {color:'red'} }, null), _parent, undefined, {
+ style: (_ctx.foo) ? null : { display: "none" }
+ })
+ _push(\`
\`)
+ }"
+ `)
+ })
+
test('with static style', () => {
expect(compileWithWrapper(``).code)
.toMatchInlineSnapshot(`
diff --git a/packages/compiler-ssr/src/transforms/ssrTransformComponent.ts b/packages/compiler-ssr/src/transforms/ssrTransformComponent.ts
index cad1ee81028..6b730088e06 100644
--- a/packages/compiler-ssr/src/transforms/ssrTransformComponent.ts
+++ b/packages/compiler-ssr/src/transforms/ssrTransformComponent.ts
@@ -30,6 +30,7 @@ import {
createCallExpression,
createFunctionExpression,
createIfStatement,
+ createObjectExpression,
createReturnStatement,
createRoot,
createSimpleExpression,
@@ -134,6 +135,17 @@ export const ssrTransformComponent: NodeTransform = (node, context) => {
})
}
+ let vShowExp
+ const vShowDir = node.props.find(
+ p => p.type === NodeTypes.DIRECTIVE && p.name === 'show',
+ ) as DirectiveNode | undefined
+ if (vShowDir) {
+ node.props = node.props.filter(p => p !== vShowDir)
+ const directiveTransform = context.directiveTransforms['show']
+ const { props } = directiveTransform!(vShowDir, node, context)
+ vShowExp = createObjectExpression(props)
+ }
+
let propsExp: string | JSChildNode = `null`
if (node.props.length) {
// note we are not passing ssr: true here because for components, v-on
@@ -180,22 +192,31 @@ export const ssrTransformComponent: NodeTransform = (node, context) => {
// dynamic component that resolved to a `resolveDynamicComponent` call
// expression - since the resolved result may be a plain element (string)
// or a VNode, handle it with `renderVNode`.
+ const args: (string | JSChildNode)[] = [
+ `_push`,
+ createCallExpression(context.helper(CREATE_VNODE), [
+ component,
+ propsExp,
+ slots,
+ ]),
+ `_parent`,
+ ]
+ if (vShowExp) args.push(`undefined`, vShowExp)
node.ssrCodegenNode = createCallExpression(
context.helper(SSR_RENDER_VNODE),
- [
- `_push`,
- createCallExpression(context.helper(CREATE_VNODE), [
- component,
- propsExp,
- slots,
- ]),
- `_parent`,
- ],
+ args,
)
} else {
+ const args: (string | JSChildNode)[] = [
+ component,
+ propsExp,
+ slots,
+ `_parent`,
+ ]
+ if (vShowExp) args.push(`undefined`, vShowExp)
node.ssrCodegenNode = createCallExpression(
context.helper(SSR_RENDER_COMPONENT),
- [component, propsExp, slots, `_parent`],
+ args,
)
}
}
diff --git a/packages/server-renderer/__tests__/ssrDirectives.spec.ts b/packages/server-renderer/__tests__/ssrDirectives.spec.ts
index dfdebe971f5..f0a947f49bd 100644
--- a/packages/server-renderer/__tests__/ssrDirectives.spec.ts
+++ b/packages/server-renderer/__tests__/ssrDirectives.spec.ts
@@ -66,6 +66,38 @@ describe('ssr: directives', () => {
),
).toBe(``)
})
+
+ test('with component', async () => {
+ expect(
+ await renderToString(
+ createApp({
+ components: {
+ Foo: {
+ template: `
`,
+ },
+ },
+ data: () => ({ show: false }),
+ template: ``,
+ }),
+ ),
+ ).toBe(`
`)
+ })
+
+ test('with dynamic component', async () => {
+ expect(
+ await renderToString(
+ createApp({
+ components: {
+ Foo: {
+ template: `
`,
+ },
+ },
+ data: () => ({ show: false }),
+ template: ``,
+ }),
+ ),
+ ).toBe(`
`)
+ })
})
describe('template v-model', () => {
diff --git a/packages/server-renderer/src/helpers/ssrRenderComponent.ts b/packages/server-renderer/src/helpers/ssrRenderComponent.ts
index 4277bb1747e..94ec2d50f77 100644
--- a/packages/server-renderer/src/helpers/ssrRenderComponent.ts
+++ b/packages/server-renderer/src/helpers/ssrRenderComponent.ts
@@ -13,10 +13,12 @@ export function ssrRenderComponent(
children: Slots | SSRSlots | null = null,
parentComponent: ComponentInternalInstance | null = null,
slotScopeId?: string,
+ vShowValue?: Props,
): SSRBuffer | Promise {
return renderComponentVNode(
createVNode(comp, props, children),
parentComponent,
slotScopeId,
+ vShowValue,
)
}
diff --git a/packages/server-renderer/src/render.ts b/packages/server-renderer/src/render.ts
index f04080b9c31..af95a2fbc6e 100644
--- a/packages/server-renderer/src/render.ts
+++ b/packages/server-renderer/src/render.ts
@@ -92,6 +92,7 @@ export function renderComponentVNode(
vnode: VNode,
parentComponent: ComponentInternalInstance | null = null,
slotScopeId?: string,
+ vShowValue?: Props,
): SSRBuffer | Promise {
const instance = (vnode.component = createComponentInstance(
vnode,
@@ -116,15 +117,18 @@ export function renderComponentVNode(
})
// Note: error display is already done by the wrapped lifecycle hook function.
.catch(NOOP)
- return p.then(() => renderComponentSubTree(instance, slotScopeId))
+ return p.then(() =>
+ renderComponentSubTree(instance, slotScopeId, vShowValue),
+ )
} else {
- return renderComponentSubTree(instance, slotScopeId)
+ return renderComponentSubTree(instance, slotScopeId, vShowValue)
}
}
function renderComponentSubTree(
instance: ComponentInternalInstance,
slotScopeId?: string,
+ vShowValue?: Props,
): SSRBuffer | Promise {
if (__DEV__) pushWarningContext(instance.vnode)
const comp = instance.type as Component
@@ -186,6 +190,12 @@ function renderComponentSubTree(
}
}
+ if (vShowValue) {
+ // v-show has higher priority
+ if (attrs) attrs = mergeProps(attrs, vShowValue)
+ else attrs = vShowValue
+ }
+
// set current rendering instance for asset resolution
const prev = setCurrentRenderingInstance(instance)
try {
@@ -225,6 +235,7 @@ export function renderVNode(
vnode: VNode,
parentComponent: ComponentInternalInstance,
slotScopeId?: string,
+ vShowValue?: Props,
): void {
const { type, shapeFlag, children, dirs, props } = vnode
if (dirs) {
@@ -263,7 +274,9 @@ export function renderVNode(
if (shapeFlag & ShapeFlags.ELEMENT) {
renderElementVNode(push, vnode, parentComponent, slotScopeId)
} else if (shapeFlag & ShapeFlags.COMPONENT) {
- push(renderComponentVNode(vnode, parentComponent, slotScopeId))
+ push(
+ renderComponentVNode(vnode, parentComponent, slotScopeId, vShowValue),
+ )
} else if (shapeFlag & ShapeFlags.TELEPORT) {
renderTeleportVNode(push, vnode, parentComponent, slotScopeId)
} else if (shapeFlag & ShapeFlags.SUSPENSE) {