Skip to content

Commit 8ed97a3

Browse files
committed
feat(compiler-vapor): impl dynamic slot name
1 parent 0c0a131 commit 8ed97a3

File tree

6 files changed

+65
-48
lines changed

6 files changed

+65
-48
lines changed

packages/compiler-vapor/__tests__/transforms/__snapshots__/vSlot.spec.ts.snap

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,19 @@
11
// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
22

3+
exports[`compiler: transform slot > dynamic slots name 1`] = `
4+
"import { resolveComponent as _resolveComponent, createComponent as _createComponent, template as _template } from 'vue/vapor';
5+
const t0 = _template("foo")
6+
7+
export function render(_ctx) {
8+
const _component_Comp = _resolveComponent("Comp")
9+
const n2 = _createComponent(_component_Comp, null, { [_ctx.dynamicName]: () => {
10+
const n0 = t0()
11+
return n0
12+
} }, null, true)
13+
return n2
14+
}"
15+
`;
16+
317
exports[`compiler: transform slot > implicit default slot 1`] = `
418
"import { resolveComponent as _resolveComponent, createComponent as _createComponent, template as _template } from 'vue/vapor';
519
const t0 = _template("<div></div>")

packages/compiler-vapor/__tests__/transforms/vSlot.spec.ts

Lines changed: 22 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
1+
import { createSimpleExpression } from '@vue/compiler-dom'
12
import {
3+
type CreateComponentIRNode,
24
IRNodeTypes,
35
transformChildren,
46
transformElement,
@@ -34,22 +36,10 @@ describe('compiler: transform slot', () => {
3436
expect(code).toMatchSnapshot()
3537

3638
expect(ir.template).toEqual(['<div></div>'])
37-
expect(ir.block.operation).toMatchObject([
38-
{
39-
type: IRNodeTypes.CREATE_COMPONENT_NODE,
40-
id: 1,
41-
tag: 'Comp',
42-
props: [[]],
43-
slots: {
44-
default: {
45-
type: IRNodeTypes.BLOCK,
46-
dynamic: {
47-
children: [{ template: 0 }],
48-
},
49-
},
50-
},
51-
},
52-
])
39+
expect(ir.block.operation[0].type).toBe(IRNodeTypes.CREATE_COMPONENT_NODE)
40+
const slots = (ir.block.operation[0] as CreateComponentIRNode).slots!
41+
expect(slots.length).toBe(1)
42+
expect(slots[0].name.content).toBe('default')
5343
expect(ir.block.returns).toEqual([1])
5444
expect(ir.block.dynamic).toMatchObject({
5545
children: [{ id: 1 }],
@@ -65,28 +55,11 @@ describe('compiler: transform slot', () => {
6555
expect(code).toMatchSnapshot()
6656

6757
expect(ir.template).toEqual(['foo', 'bar', '<span></span>'])
68-
expect(ir.block.operation).toMatchObject([
69-
{
70-
type: IRNodeTypes.CREATE_COMPONENT_NODE,
71-
id: 4,
72-
tag: 'Comp',
73-
props: [[]],
74-
slots: {
75-
one: {
76-
type: IRNodeTypes.BLOCK,
77-
dynamic: {
78-
children: [{ template: 0 }],
79-
},
80-
},
81-
default: {
82-
type: IRNodeTypes.BLOCK,
83-
dynamic: {
84-
children: [{}, { template: 1 }, { template: 2 }],
85-
},
86-
},
87-
},
88-
},
89-
])
58+
expect(ir.block.operation[0].type).toBe(IRNodeTypes.CREATE_COMPONENT_NODE)
59+
const slots = (ir.block.operation[0] as CreateComponentIRNode).slots!
60+
expect(slots.length).toBe(2)
61+
expect(slots[0].name.content).toBe('one')
62+
expect(slots[1].name.content).toBe('default')
9063
})
9164

9265
test('nested slots', () => {
@@ -97,4 +70,15 @@ describe('compiler: transform slot', () => {
9770
)
9871
expect(code).toMatchSnapshot()
9972
})
73+
74+
test('dynamic slots name', () => {
75+
const { ir, code } = compileWithSlots(`<Comp>
76+
<template #[dynamicName]>foo</template>
77+
</Comp>`)
78+
expect(ir.block.operation[0].type).toBe(IRNodeTypes.CREATE_COMPONENT_NODE)
79+
const slots = (ir.block.operation[0] as CreateComponentIRNode).slots!
80+
expect(slots.length).toBe(1)
81+
expect(slots[0].name.isStatic).toBe(false)
82+
expect(code).toMatchSnapshot()
83+
})
10084
})

packages/compiler-vapor/src/generators/component.ts

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -138,11 +138,17 @@ function genModelModifiers(
138138
}
139139

140140
function genSlots(oper: CreateComponentIRNode, context: CodegenContext) {
141-
const slotList = Object.entries(oper.slots!)
141+
const slotList = oper.slots!
142142
return genMulti(
143143
slotList.length > 1 ? SEGMENTS_OBJECT_NEWLINE : SEGMENTS_OBJECT,
144-
...slotList.map(([name, slot]) => {
145-
return [name, ': ', ...genBlock(slot, context)]
144+
...slotList.map(({ name, block }) => {
145+
return [
146+
...(name.isStatic
147+
? [name.content]
148+
: ['[', ...genExpression(name, context), ']']),
149+
': ',
150+
...genBlock(block, context),
151+
]
146152
}),
147153
)
148154
}

packages/compiler-vapor/src/ir.ts

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -199,6 +199,11 @@ export interface WithDirectiveIRNode extends BaseIRNode {
199199
builtin?: VaporHelper
200200
}
201201

202+
export interface ComponentStaticSlot {
203+
name: SimpleExpressionNode
204+
block: ComponentSlotBlockIRNode
205+
}
206+
202207
export interface ComponentSlotBlockIRNode extends BlockIRNode {}
203208
export interface ComponentDynamicSlot {
204209
name: SimpleExpressionNode
@@ -212,7 +217,7 @@ export interface CreateComponentIRNode extends BaseIRNode {
212217
tag: string
213218
props: IRProps[]
214219

215-
slots?: Record<string, ComponentSlotBlockIRNode>
220+
slots?: ComponentStaticSlot[]
216221
dynamicSlots?: ComponentDynamicSlot[]
217222

218223
resolve: boolean

packages/compiler-vapor/src/transform.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ import {
1616
import { EMPTY_OBJ, NOOP, extend, isArray, isString } from '@vue/shared'
1717
import {
1818
type BlockIRNode,
19-
type ComponentSlotBlockIRNode,
19+
type ComponentStaticSlot,
2020
DynamicFlag,
2121
type HackOptions,
2222
type IRDynamicInfo,
@@ -78,7 +78,7 @@ export class TransformContext<T extends AllNode = AllNode> {
7878

7979
comment: CommentNode[] = []
8080
component: Set<string> = this.ir.component
81-
slots: Record<string, ComponentSlotBlockIRNode> | null = null
81+
slots: ComponentStaticSlot[] | null = null
8282

8383
private globalId = 0
8484

packages/compiler-vapor/src/transforms/vSlot.ts

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import {
22
type ElementNode,
33
ElementTypes,
44
NodeTypes,
5+
createSimpleExpression,
56
isTemplateNode,
67
isVSlot,
78
} from '@vue/compiler-core'
@@ -35,12 +36,16 @@ export const transformVSlot: NodeTransform = (node, context) => {
3536
context as TransformContext<ElementNode>,
3637
)
3738

38-
const slots = (context.slots ||= {})
39+
const slots = (context.slots ||= [])
3940

4041
return () => {
4142
onExit()
42-
if (hasDefalutSlot) slots.default = block
43-
if (Object.keys(slots).length) context.slots = slots
43+
if (hasDefalutSlot)
44+
slots.push({
45+
name: createSimpleExpression('default', true),
46+
block,
47+
})
48+
if (slots.length) context.slots = slots
4449
}
4550
} else if (isSlotTemplate && (dir = findDir(node, 'slot', true))) {
4651
context.dynamic.flags |= DynamicFlag.NON_TEMPLATE
@@ -52,7 +57,10 @@ export const transformVSlot: NodeTransform = (node, context) => {
5257
context as TransformContext<ElementNode>,
5358
)
5459

55-
slots[dir.arg!.content] = block
60+
slots.push({
61+
name: dir.arg!,
62+
block,
63+
})
5664
return () => onExit()
5765
}
5866
}

0 commit comments

Comments
 (0)