fix(ssr): render fallthrough attributes for transition-group with tag

fix #5141
This commit is contained in:
Evan You
2022-05-18 09:55:39 +08:00
parent 1035c6b51b
commit aed10c5072
3 changed files with 98 additions and 10 deletions

View File

@@ -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.

View File

@@ -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<ComponentNode, WIPEntry>()
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}>`)
}