mirror of https://github.com/vuejs/core.git
feat(compiler-vapor): add support for forwarded slots
This commit is contained in:
parent
1ef6e6edb7
commit
dde7076120
|
@ -18,6 +18,7 @@ import {
|
|||
genCall,
|
||||
} from './generators/utils'
|
||||
import { setTemplateRefIdent } from './generators/templateRef'
|
||||
import { createForwardedSlotIdent } from './generators/slotOutlet'
|
||||
|
||||
export type CodegenOptions = Omit<BaseCodegenOptions, 'optimizeImports'>
|
||||
|
||||
|
@ -129,6 +130,12 @@ export function generate(
|
|||
`const ${setTemplateRefIdent} = ${context.helper('createTemplateRefSetter')}()`,
|
||||
)
|
||||
}
|
||||
if (ir.hasForwardedSlot) {
|
||||
push(
|
||||
NEWLINE,
|
||||
`const ${createForwardedSlotIdent} = ${context.helper('forwardedSlotCreator')}()`,
|
||||
)
|
||||
}
|
||||
push(...genBlockContent(ir.block, context, true))
|
||||
push(INDENT_END, NEWLINE)
|
||||
|
||||
|
|
|
@ -5,12 +5,14 @@ import { genExpression } from './expression'
|
|||
import { type CodeFragment, NEWLINE, buildCodeFragment, genCall } from './utils'
|
||||
import { genRawProps } from './component'
|
||||
|
||||
export const createForwardedSlotIdent = `_createForwardedSlot`
|
||||
|
||||
export function genSlotOutlet(
|
||||
oper: SlotOutletIRNode,
|
||||
context: CodegenContext,
|
||||
): CodeFragment[] {
|
||||
const { helper } = context
|
||||
const { id, name, fallback } = oper
|
||||
const { id, name, fallback, forwarded } = oper
|
||||
const [frag, push] = buildCodeFragment()
|
||||
|
||||
const nameExpr = name.isStatic
|
||||
|
@ -26,7 +28,7 @@ export function genSlotOutlet(
|
|||
NEWLINE,
|
||||
`const n${id} = `,
|
||||
...genCall(
|
||||
helper('createSlot'),
|
||||
forwarded ? createForwardedSlotIdent : helper('createSlot'),
|
||||
nameExpr,
|
||||
genRawProps(oper.props, context) || 'null',
|
||||
fallbackArg,
|
||||
|
|
|
@ -66,6 +66,7 @@ export interface RootIRNode {
|
|||
directive: Set<string>
|
||||
block: BlockIRNode
|
||||
hasTemplateRef: boolean
|
||||
hasForwardedSlot: boolean
|
||||
}
|
||||
|
||||
export interface IfIRNode extends BaseIRNode {
|
||||
|
@ -209,6 +210,7 @@ export interface SlotOutletIRNode extends BaseIRNode {
|
|||
name: SimpleExpressionNode
|
||||
props: IRProps[]
|
||||
fallback?: BlockIRNode
|
||||
forwarded?: boolean
|
||||
parent?: number
|
||||
anchor?: number
|
||||
}
|
||||
|
|
|
@ -230,6 +230,7 @@ export function transform(
|
|||
directive: new Set(),
|
||||
block: newBlock(node),
|
||||
hasTemplateRef: false,
|
||||
hasForwardedSlot: false,
|
||||
}
|
||||
|
||||
const context = new TransformContext(ir, node, options)
|
||||
|
|
|
@ -5,6 +5,7 @@ import {
|
|||
ErrorCodes,
|
||||
NodeTypes,
|
||||
type SimpleExpressionNode,
|
||||
type TemplateChildNode,
|
||||
createCompilerError,
|
||||
createSimpleExpression,
|
||||
isStaticArgOf,
|
||||
|
@ -99,6 +100,13 @@ export const transformSlotOutlet: NodeTransform = (node, context) => {
|
|||
}
|
||||
|
||||
return () => {
|
||||
let forwarded = false
|
||||
const slotNode = context.block.node
|
||||
if (slotNode.type === NodeTypes.ELEMENT) {
|
||||
forwarded = hasForwardedSlots(slotNode.children)
|
||||
}
|
||||
if (forwarded) context.ir.hasForwardedSlot = true
|
||||
|
||||
exitBlock && exitBlock()
|
||||
context.dynamic.operation = {
|
||||
type: IRNodeTypes.SLOT_OUTLET_NODE,
|
||||
|
@ -106,6 +114,7 @@ export const transformSlotOutlet: NodeTransform = (node, context) => {
|
|||
name: slotName,
|
||||
props: irProps,
|
||||
fallback,
|
||||
forwarded,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -131,3 +140,21 @@ function createFallback(
|
|||
context.reference()
|
||||
return [fallback, exitBlock]
|
||||
}
|
||||
|
||||
// TODO
|
||||
function hasForwardedSlots(children: TemplateChildNode[]): boolean {
|
||||
for (let i = 0; i < children.length; i++) {
|
||||
const child = children[i]
|
||||
switch (child.type) {
|
||||
case NodeTypes.ELEMENT:
|
||||
if (
|
||||
child.tagType === ElementTypes.SLOT ||
|
||||
hasForwardedSlots(child.children)
|
||||
) {
|
||||
return true
|
||||
}
|
||||
break
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
|
|
@ -87,10 +87,24 @@ export function getSlot(
|
|||
}
|
||||
}
|
||||
|
||||
export function forwardedSlotCreator(): (
|
||||
name: string | (() => string),
|
||||
rawProps?: LooseRawProps | null,
|
||||
fallback?: VaporSlot,
|
||||
) => Block {
|
||||
const instance = currentInstance as VaporComponentInstance
|
||||
return (
|
||||
name: string | (() => string),
|
||||
rawProps?: LooseRawProps | null,
|
||||
fallback?: VaporSlot,
|
||||
) => createSlot(name, rawProps, fallback, instance)
|
||||
}
|
||||
|
||||
export function createSlot(
|
||||
name: string | (() => string),
|
||||
rawProps?: LooseRawProps | null,
|
||||
fallback?: VaporSlot,
|
||||
i?: VaporComponentInstance,
|
||||
): Block {
|
||||
const _insertionParent = insertionParent
|
||||
const _insertionAnchor = insertionAnchor
|
||||
|
@ -98,7 +112,7 @@ export function createSlot(
|
|||
locateHydrationNode()
|
||||
}
|
||||
|
||||
const instance = currentInstance as VaporComponentInstance
|
||||
const instance = i || (currentInstance as VaporComponentInstance)
|
||||
const rawSlots = instance.rawSlots
|
||||
const slotProps = rawProps
|
||||
? new Proxy(rawProps, rawPropsProxyHandlers)
|
||||
|
|
|
@ -9,7 +9,7 @@ export { insert, prepend, remove, isFragment, VaporFragment } from './block'
|
|||
export { setInsertionState } from './insertionState'
|
||||
export { createComponent, createComponentWithFallback } from './component'
|
||||
export { renderEffect } from './renderEffect'
|
||||
export { createSlot } from './componentSlots'
|
||||
export { createSlot, forwardedSlotCreator } from './componentSlots'
|
||||
export { template } from './dom/template'
|
||||
export { createTextNode, child, nthChild, next } from './dom/node'
|
||||
export {
|
||||
|
|
Loading…
Reference in New Issue