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