Skip to content

Commit a5fe2b0

Browse files
committed
feat(compiler): support v-slot
1 parent b7ea8d3 commit a5fe2b0

File tree

14 files changed

+652
-11
lines changed

14 files changed

+652
-11
lines changed

package.json

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -159,5 +159,10 @@
159159
"vite": "^5.3.2",
160160
"vitest": "^1.6.0",
161161
"webpack": "^5.92.1"
162+
},
163+
"pnpm": {
164+
"patchedDependencies": {
165+
"@vue-vapor/[email protected]": "patches/@[email protected]"
166+
}
162167
}
163168
}

patches/@[email protected]

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
diff --git a/dist/compiler-vapor.cjs.js b/dist/compiler-vapor.cjs.js
2+
index 8f54d6d74f28eef89b0c9234de66fa02d95d477a..eb05dacd92822ab1b12e3025a0d97204f53fc530 100644
3+
--- a/dist/compiler-vapor.cjs.js
4+
+++ b/dist/compiler-vapor.cjs.js
5+
@@ -1392,7 +1392,7 @@ function genRawSlots(slots, context) {
6+
return genMulti(
7+
DELIMITERS_ARRAY_NEWLINE,
8+
...slots.map(
9+
- (slot) => slot.slotType === 0 ? genStaticSlots(slot, context) : genDynamicSlot(slot, context, true)
10+
+ (slot) => slot.slotType === 0 ? genStaticSlots(slot, context) : slot.slotType === 4 ? slot.slots.content : genDynamicSlot(slot, context, true)
11+
)
12+
);
13+
}

playground/App.vue

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import { defineComponent, ref } from 'vue'
33
import Count2 from './Count.vue'
44
import If from './if.vue'
55
import For from './for.vue'
6+
import Slot from './slot.vue'
67
78
export default defineComponent({
89
setup() {
@@ -39,6 +40,11 @@ export default defineComponent({
3940
<legend>v-for</legend>
4041
<For></For>
4142
</fieldset>
43+
44+
<fieldset>
45+
<legend>v-slot</legend>
46+
<Slot></Slot>
47+
</fieldset>
4248
</>
4349
)
4450
},

playground/for.vue

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ export default defineComponent({
66
const count = ref(3)
77
88
return (
9-
<div style="text-align:center">
9+
<div>
1010
<input value={count.value} onInput={e => count.value = e.target.value} type="number" />
1111
1212
{Array.from({length: count.value}).map((item,index) =>{

playground/slot.vue

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
<script lang="tsx">
2+
import { defineComponent } from 'vue'
3+
4+
const Comp = (props, { slots }) => (
5+
<>{slots.default ? <slots.default /> : <div>default slot</div>}</>
6+
)
7+
8+
let slots = { default: () => <div>foo</div> }
9+
10+
export default defineComponent({
11+
setup(props) {
12+
return <Comp v-slots={slots}></Comp>
13+
},
14+
})
15+
</script>

pnpm-lock.yaml

Lines changed: 9 additions & 4 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/core/compiler/compile.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,11 @@ import {
55
defaultOnError,
66
} from '@vue-vapor/compiler-dom'
77
import { extend, isString } from '@vue-vapor/shared'
8+
import { babelParse } from '@vue-macros/common'
89
import {
910
type VaporCodegenResult as BaseVaporCodegenResult,
1011
generate,
1112
} from '@vue-vapor/compiler-vapor'
12-
import { babelParse } from '@vue-macros/common'
1313
import {
1414
type DirectiveTransform,
1515
type NodeTransform,
@@ -27,6 +27,7 @@ import {
2727
import { transformText } from './transforms/transformText'
2828
import { transformVBind } from './transforms/vBind'
2929
import { transformVOn } from './transforms/vOn'
30+
import { transformVSlot } from './transforms/vSlot'
3031
import type { JSXElement, JSXFragment, Program } from '@babel/types'
3132

3233
export interface VaporCodegenResult
@@ -124,7 +125,7 @@ export function getBaseTransformPreset(
124125
prefixIdentifiers?: boolean,
125126
): TransformPreset {
126127
return [
127-
[transformText, transformElement, transformChildren],
128+
[transformText, transformElement, transformVSlot, transformChildren],
128129
{
129130
bind: transformVBind,
130131
on: transformVOn,

src/core/compiler/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,3 +15,4 @@ export { transformElement } from './transforms/transformElement'
1515
export { transformChildren } from './transforms/transformChildren'
1616
export { transformVBind } from './transforms/vBind'
1717
export { transformVOn } from './transforms/vOn'
18+
export { transformVSlot } from './transforms/vSlot'

src/core/compiler/ir/component.ts

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ export enum IRSlotType {
3737
DYNAMIC,
3838
LOOP,
3939
CONDITIONAL,
40+
EXPRESSION,
4041
}
4142
export interface IRSlotsStatic {
4243
slotType: IRSlotType.STATIC
@@ -59,9 +60,13 @@ export interface IRSlotDynamicConditional {
5960
positive: IRSlotDynamicBasic
6061
negative?: IRSlotDynamicBasic | IRSlotDynamicConditional
6162
}
63+
export interface IRSlotsExpression {
64+
slotType: IRSlotType.EXPRESSION
65+
slots: SimpleExpressionNode
66+
}
6267

6368
export type IRSlotDynamic =
6469
| IRSlotDynamicBasic
6570
| IRSlotDynamicLoop
6671
| IRSlotDynamicConditional
67-
export type IRSlots = IRSlotsStatic | IRSlotDynamic
72+
export type IRSlots = IRSlotsStatic | IRSlotDynamic | IRSlotsExpression

src/core/compiler/transforms/transformChildren.ts

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,13 +4,16 @@ import {
44
type TransformContext,
55
transformNode,
66
} from '../transform'
7+
import { isComponentNode } from '../utils'
78
import type { Node } from '@babel/types'
89

910
export const transformChildren: NodeTransform = (node, context) => {
1011
const isFragment =
11-
node.type === IRNodeTypes.ROOT || node.type === 'JSXFragment'
12+
node.type === IRNodeTypes.ROOT ||
13+
node.type === 'JSXFragment' ||
14+
isComponentNode(node)
1215

13-
if (!isFragment && node.type !== 'JSXElement') return
16+
if (node.type !== 'JSXElement' && !isFragment) return
1417

1518
Array.from(node.children).forEach((child, index) => {
1619
if (child.type === 'JSXText' && !child.value.trim()) {

0 commit comments

Comments
 (0)