fix(compiler/v-slot): handle implicit default slot mixed with named slots
This commit is contained in:
@@ -117,9 +117,9 @@ export function buildSlots(
|
||||
|
||||
// 1. Check for default slot with slotProps on component itself.
|
||||
// <Comp v-slot="{ prop }"/>
|
||||
const explicitDefaultSlot = findDir(node, 'slot', true)
|
||||
if (explicitDefaultSlot) {
|
||||
const { arg, exp, loc } = explicitDefaultSlot
|
||||
const onComponentDefaultSlot = findDir(node, 'slot', true)
|
||||
if (onComponentDefaultSlot) {
|
||||
const { arg, exp, loc } = onComponentDefaultSlot
|
||||
if (arg) {
|
||||
context.onError(
|
||||
createCompilerError(ErrorCodes.X_V_SLOT_NAMED_SLOT_ON_COMPONENT, loc)
|
||||
@@ -131,8 +131,10 @@ export function buildSlots(
|
||||
// 2. Iterate through children and check for template slots
|
||||
// <template v-slot:foo="{ prop }">
|
||||
let hasTemplateSlots = false
|
||||
let extraneousChild: TemplateChildNode | undefined = undefined
|
||||
let hasNamedDefaultSlot = false
|
||||
const implicitDefaultChildren: TemplateChildNode[] = []
|
||||
const seenSlotNames = new Set<string>()
|
||||
|
||||
for (let i = 0; i < children.length; i++) {
|
||||
const slotElement = children[i]
|
||||
let slotDir
|
||||
@@ -142,13 +144,13 @@ export function buildSlots(
|
||||
!(slotDir = findDir(slotElement, 'slot', true))
|
||||
) {
|
||||
// not a <template v-slot>, skip.
|
||||
if (slotElement.type !== NodeTypes.COMMENT && !extraneousChild) {
|
||||
extraneousChild = slotElement
|
||||
if (slotElement.type !== NodeTypes.COMMENT) {
|
||||
implicitDefaultChildren.push(slotElement)
|
||||
}
|
||||
continue
|
||||
}
|
||||
|
||||
if (explicitDefaultSlot) {
|
||||
if (onComponentDefaultSlot) {
|
||||
// already has on-component default slot - this is incorrect usage.
|
||||
context.onError(
|
||||
createCompilerError(ErrorCodes.X_V_SLOT_MIXED_SLOT_USAGE, slotDir.loc)
|
||||
@@ -267,23 +269,33 @@ export function buildSlots(
|
||||
continue
|
||||
}
|
||||
seenSlotNames.add(staticSlotName)
|
||||
if (staticSlotName === 'default') {
|
||||
hasNamedDefaultSlot = true
|
||||
}
|
||||
}
|
||||
slotsProperties.push(createObjectProperty(slotName, slotFunction))
|
||||
}
|
||||
}
|
||||
|
||||
if (hasTemplateSlots && extraneousChild) {
|
||||
context.onError(
|
||||
createCompilerError(
|
||||
ErrorCodes.X_V_SLOT_EXTRANEOUS_NON_SLOT_CHILDREN,
|
||||
extraneousChild.loc
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
if (!explicitDefaultSlot && !hasTemplateSlots) {
|
||||
// implicit default slot.
|
||||
slotsProperties.push(buildDefaultSlot(undefined, children, loc))
|
||||
if (!onComponentDefaultSlot) {
|
||||
if (!hasTemplateSlots) {
|
||||
// implicit default slot (on component)
|
||||
slotsProperties.push(buildDefaultSlot(undefined, children, loc))
|
||||
} else if (implicitDefaultChildren.length) {
|
||||
// implicit default slot (mixed with named slots)
|
||||
if (hasNamedDefaultSlot) {
|
||||
context.onError(
|
||||
createCompilerError(
|
||||
ErrorCodes.X_V_SLOT_EXTRANEOUS_DEFAULT_SLOT_CHILDREN,
|
||||
implicitDefaultChildren[0].loc
|
||||
)
|
||||
)
|
||||
} else {
|
||||
slotsProperties.push(
|
||||
buildDefaultSlot(undefined, implicitDefaultChildren, loc)
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let slots: ObjectExpression | CallExpression = createObjectExpression(
|
||||
|
||||
Reference in New Issue
Block a user