| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118 |
- import {
- type AttributeNode,
- type ComponentNode,
- type DirectiveNode,
- type JSChildNode,
- NodeTypes,
- type TransformContext,
- buildProps,
- createCallExpression,
- findProp,
- } from '@vue/compiler-dom'
- import { SSR_RENDER_ATTRS } from '../runtimeHelpers'
- import {
- type SSRTransformContext,
- processChildren,
- } from '../ssrCodegenTransform'
- import { buildSSRProps } from './ssrTransformElement'
- const wipMap = new WeakMap<ComponentNode, WIPEntry>()
- interface WIPEntry {
- tag: AttributeNode | DirectiveNode
- propsExp: string | JSChildNode | null
- scopeId: string | 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,
- scopeId: context.scopeId || null,
- })
- }
- }
- }
- // phase 2: process children
- export function ssrProcessTransitionGroup(
- node: ComponentNode,
- context: SSRTransformContext,
- ) {
- const entry = wipMap.get(node)
- if (entry) {
- const { tag, propsExp, scopeId } = entry
- if (tag.type === NodeTypes.DIRECTIVE) {
- // dynamic :tag
- context.pushStringPart(`<`)
- context.pushStringPart(tag.exp!)
- if (propsExp) {
- context.pushStringPart(propsExp)
- }
- if (scopeId) {
- context.pushStringPart(` ${scopeId}`)
- }
- context.pushStringPart(`>`)
- processChildren(
- node,
- context,
- false,
- /**
- * TransitionGroup has the special runtime behavior of flattening and
- * concatenating all children into a single fragment (in order for them to
- * be patched using the same key map) so we need to account for that here
- * by disabling nested fragment wrappers from being generated.
- */
- true,
- /**
- * TransitionGroup filters out comment children at runtime and thus
- * doesn't expect comments to be present during hydration. We need to
- * account for that by disabling the empty comment that is otherwise
- * rendered for a falsy v-if that has no v-else specified. (#6715)
- */
- true,
- )
- context.pushStringPart(`</`)
- context.pushStringPart(tag.exp!)
- context.pushStringPart(`>`)
- } else {
- // static tag
- context.pushStringPart(`<${tag.value!.content}`)
- if (propsExp) {
- context.pushStringPart(propsExp)
- }
- if (scopeId) {
- context.pushStringPart(` ${scopeId}`)
- }
- context.pushStringPart(`>`)
- processChildren(node, context, false, true)
- context.pushStringPart(`</${tag.value!.content}>`)
- }
- } else {
- // fragment
- processChildren(node, context, true, true, true)
- }
- }
|