wip(srr): slot outlet
This commit is contained in:
@@ -1,78 +1,32 @@
|
||||
import { NodeTransform } from '../transform'
|
||||
import { NodeTransform, TransformContext } from '../transform'
|
||||
import {
|
||||
NodeTypes,
|
||||
CallExpression,
|
||||
createCallExpression,
|
||||
ExpressionNode
|
||||
ExpressionNode,
|
||||
SlotOutletNode
|
||||
} from '../ast'
|
||||
import { isSlotOutlet } from '../utils'
|
||||
import { buildProps } from './transformElement'
|
||||
import { isSlotOutlet, findProp } from '../utils'
|
||||
import { buildProps, PropsExpression } from './transformElement'
|
||||
import { createCompilerError, ErrorCodes } from '../errors'
|
||||
import { RENDER_SLOT } from '../runtimeHelpers'
|
||||
|
||||
export const transformSlotOutlet: NodeTransform = (node, context) => {
|
||||
if (isSlotOutlet(node)) {
|
||||
const { props, children, loc } = node
|
||||
const $slots = context.prefixIdentifiers ? `_ctx.$slots` : `$slots`
|
||||
let slotName: string | ExpressionNode = `"default"`
|
||||
const { children, loc } = node
|
||||
const { slotName, slotProps } = processSlotOutlet(node, context)
|
||||
|
||||
// check for <slot name="xxx" OR :name="xxx" />
|
||||
let nameIndex: number = -1
|
||||
for (let i = 0; i < props.length; i++) {
|
||||
const prop = props[i]
|
||||
if (prop.type === NodeTypes.ATTRIBUTE) {
|
||||
if (prop.name === `name` && prop.value) {
|
||||
// static name="xxx"
|
||||
slotName = JSON.stringify(prop.value.content)
|
||||
nameIndex = i
|
||||
break
|
||||
}
|
||||
} else if (prop.name === `bind`) {
|
||||
const { arg, exp } = prop
|
||||
if (
|
||||
arg &&
|
||||
exp &&
|
||||
arg.type === NodeTypes.SIMPLE_EXPRESSION &&
|
||||
arg.isStatic &&
|
||||
arg.content === `name`
|
||||
) {
|
||||
// dynamic :name="xxx"
|
||||
slotName = exp
|
||||
nameIndex = i
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
const slotArgs: CallExpression['arguments'] = [
|
||||
context.prefixIdentifiers ? `_ctx.$slots` : `$slots`,
|
||||
slotName
|
||||
]
|
||||
|
||||
const slotArgs: CallExpression['arguments'] = [$slots, slotName]
|
||||
const propsWithoutName =
|
||||
nameIndex > -1
|
||||
? props.slice(0, nameIndex).concat(props.slice(nameIndex + 1))
|
||||
: props
|
||||
let hasProps = propsWithoutName.length > 0
|
||||
if (hasProps) {
|
||||
const { props: propsExpression, directives } = buildProps(
|
||||
node,
|
||||
context,
|
||||
propsWithoutName
|
||||
)
|
||||
if (directives.length) {
|
||||
context.onError(
|
||||
createCompilerError(
|
||||
ErrorCodes.X_V_SLOT_UNEXPECTED_DIRECTIVE_ON_SLOT_OUTLET,
|
||||
directives[0].loc
|
||||
)
|
||||
)
|
||||
}
|
||||
if (propsExpression) {
|
||||
slotArgs.push(propsExpression)
|
||||
} else {
|
||||
hasProps = false
|
||||
}
|
||||
if (slotProps) {
|
||||
slotArgs.push(slotProps)
|
||||
}
|
||||
|
||||
if (children.length) {
|
||||
if (!hasProps) {
|
||||
if (!slotProps) {
|
||||
slotArgs.push(`{}`)
|
||||
}
|
||||
slotArgs.push(children)
|
||||
@@ -85,3 +39,49 @@ export const transformSlotOutlet: NodeTransform = (node, context) => {
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
interface SlotOutletProcessResult {
|
||||
slotName: string | ExpressionNode
|
||||
slotProps: PropsExpression | undefined
|
||||
}
|
||||
|
||||
export function processSlotOutlet(
|
||||
node: SlotOutletNode,
|
||||
context: TransformContext
|
||||
): SlotOutletProcessResult {
|
||||
let slotName: string | ExpressionNode = `"default"`
|
||||
let slotProps: PropsExpression | undefined = undefined
|
||||
|
||||
// check for <slot name="xxx" OR :name="xxx" />
|
||||
const name = findProp(node, 'name')
|
||||
if (name) {
|
||||
if (name.type === NodeTypes.ATTRIBUTE && name.value) {
|
||||
// static name
|
||||
slotName = JSON.stringify(name.value.content)
|
||||
} else if (name.type === NodeTypes.DIRECTIVE && name.exp) {
|
||||
// dynamic name
|
||||
slotName = name.exp
|
||||
}
|
||||
}
|
||||
|
||||
const propsWithoutName = name
|
||||
? node.props.filter(p => p !== name)
|
||||
: node.props
|
||||
if (propsWithoutName.length > 0) {
|
||||
const { props, directives } = buildProps(node, context, propsWithoutName)
|
||||
slotProps = props
|
||||
if (directives.length) {
|
||||
context.onError(
|
||||
createCompilerError(
|
||||
ErrorCodes.X_V_SLOT_UNEXPECTED_DIRECTIVE_ON_SLOT_OUTLET,
|
||||
directives[0].loc
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
slotName,
|
||||
slotProps
|
||||
}
|
||||
}
|
||||
|
||||
@@ -46,7 +46,7 @@ export const transformFor = createStructuralDirectiveTransform(
|
||||
'for',
|
||||
(node, dir, context) => {
|
||||
const { helper } = context
|
||||
return processForNode(node, dir, context, forNode => {
|
||||
return processFor(node, dir, context, forNode => {
|
||||
// create the loop render function expression now, and add the
|
||||
// iterator on exit after all children have been traversed
|
||||
const renderExp = createCallExpression(helper(RENDER_LIST), [
|
||||
@@ -138,7 +138,7 @@ export const transformFor = createStructuralDirectiveTransform(
|
||||
)
|
||||
|
||||
// target-agnostic transform used for both Client and SSR
|
||||
export function processForNode(
|
||||
export function processFor(
|
||||
node: ElementNode,
|
||||
dir: DirectiveNode,
|
||||
context: TransformContext,
|
||||
|
||||
@@ -41,7 +41,7 @@ import { injectProp } from '../utils'
|
||||
export const transformIf = createStructuralDirectiveTransform(
|
||||
/^(if|else|else-if)$/,
|
||||
(node, dir, context) => {
|
||||
return processIfBranches(node, dir, context, (ifNode, branch, isRoot) => {
|
||||
return processIf(node, dir, context, (ifNode, branch, isRoot) => {
|
||||
// Exit callback. Complete the codegenNode when all children have been
|
||||
// transformed.
|
||||
return () => {
|
||||
@@ -72,7 +72,7 @@ export const transformIf = createStructuralDirectiveTransform(
|
||||
)
|
||||
|
||||
// target-agnostic transform used for both Client and SSR
|
||||
export function processIfBranches(
|
||||
export function processIf(
|
||||
node: ElementNode,
|
||||
dir: DirectiveNode,
|
||||
context: TransformContext,
|
||||
|
||||
Reference in New Issue
Block a user