Skip to content

Commit 578c122

Browse files
Jevon617sxzz
authored andcommitted
feat(compiler-vapor): v-model for component
1 parent af1581b commit 578c122

File tree

5 files changed

+66
-22
lines changed

5 files changed

+66
-22
lines changed

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

+29-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { extend, isArray } from '@vue/shared'
1+
import { camelize, extend, isArray } from '@vue/shared'
22
import type { CodegenContext } from '../generate'
33
import type { CreateComponentIRNode, IRProp } from '../ir'
44
import {
@@ -13,6 +13,8 @@ import { genExpression } from './expression'
1313
import { genPropKey } from './prop'
1414
import { createSimpleExpression } from '@vue/compiler-dom'
1515
import { genEventHandler } from './event'
16+
import { genDirectiveModifiers } from './directive'
17+
import { genModelHandler } from './modelValue'
1618

1719
// TODO: generate component slots
1820
export function genCreateComponent(
@@ -79,8 +81,34 @@ export function genCreateComponent(
7981
...(prop.handler
8082
? genEventHandler(context, prop.values[0])
8183
: ['() => (', ...genExpression(prop.values[0], context), ')']),
84+
...(prop.model
85+
? [...genModel(prop, context), ...genModifiers(prop, context)]
86+
: []),
8287
]
8388
}),
8489
)
90+
91+
function genModel(prop: IRProp, context: CodegenContext) {
92+
const name = prop.key.isStatic
93+
? [JSON.stringify(`onUpdate:${camelize(prop.key.content)}`)]
94+
: ['[`onUpdate:${', ...genExpression(prop.key, context), '}`]']
95+
const handler = genModelHandler(prop.values[0], context)
96+
97+
return [',', ...name, ':', ...handler]
98+
}
99+
100+
function genModifiers(prop: IRProp, context: CodegenContext) {
101+
const { key, modifiers } = prop
102+
if (!isArray(modifiers) || modifiers.length === 0) return []
103+
104+
const modifiersKey = key.isStatic
105+
? key.content === 'modelValue'
106+
? [`modelModifiers`]
107+
: [`${key.content}Modifiers`]
108+
: ['[`${', ...genExpression(key, context), '}Modifiers`]']
109+
110+
const modifiersVal = genDirectiveModifiers(modifiers)
111+
return [',', ...modifiersKey, ':', `() => ({${modifiersVal}})`]
112+
}
85113
}
86114
}

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

+10-10
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ export function genWithDirective(
3535
? NULL
3636
: false
3737
const modifiers = dir.modifiers.length
38-
? ['{ ', genDirectiveModifiers(), ' }']
38+
? ['{ ', genDirectiveModifiers(dir.modifiers), ' }']
3939
: false
4040

4141
return genMulti(['[', ']', ', '], directive, value, argument, modifiers)
@@ -61,14 +61,14 @@ export function genWithDirective(
6161
}
6262
}
6363
}
64-
65-
function genDirectiveModifiers() {
66-
return dir.modifiers
67-
.map(
68-
value =>
69-
`${isSimpleIdentifier(value) ? value : JSON.stringify(value)}: true`,
70-
)
71-
.join(', ')
72-
}
7364
}
7465
}
66+
67+
export function genDirectiveModifiers(modifiers: string[]) {
68+
return modifiers
69+
.map(
70+
value =>
71+
`${isSimpleIdentifier(value) ? value : JSON.stringify(value)}: true`,
72+
)
73+
.join(', ')
74+
}

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

+19-11
Original file line numberDiff line numberDiff line change
@@ -3,28 +3,36 @@ import { genExpression } from './expression'
33
import type { SetModelValueIRNode } from '../ir'
44
import type { CodegenContext } from '../generate'
55
import { type CodeFragment, NEWLINE, genCall } from './utils'
6+
import type { SimpleExpressionNode } from '@vue/compiler-dom'
67

78
export function genSetModelValue(
89
oper: SetModelValueIRNode,
910
context: CodegenContext,
1011
): CodeFragment[] {
11-
const {
12-
vaporHelper,
13-
14-
options: { isTS },
15-
} = context
16-
12+
const { vaporHelper } = context
1713
const name = oper.key.isStatic
1814
? [JSON.stringify(`update:${camelize(oper.key.content)}`)]
1915
: ['`update:${', ...genExpression(oper.key, context), '}`']
20-
const handler = [
21-
`() => ${isTS ? `($event: any)` : `$event`} => (`,
22-
...genExpression(oper.value, context, '$event'),
23-
')',
24-
]
16+
17+
const handler = genModelHandler(oper.value, context)
2518

2619
return [
2720
NEWLINE,
2821
...genCall(vaporHelper('delegate'), `n${oper.element}`, name, handler),
2922
]
3023
}
24+
25+
export function genModelHandler(
26+
value: SimpleExpressionNode,
27+
context: CodegenContext,
28+
) {
29+
const {
30+
options: { isTS },
31+
} = context
32+
33+
return [
34+
`() => ${isTS ? `($event: any)` : `$event`} => (`,
35+
...genExpression(value, context, '$event'),
36+
')',
37+
]
38+
}

packages/compiler-vapor/src/transform.ts

+2
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,8 @@ export interface DirectiveTransformResult {
4444
modifier?: '.' | '^'
4545
runtimeCamelize?: boolean
4646
handler?: boolean
47+
model?: boolean
48+
modifiers?: string[]
4749
}
4850

4951
// A structural directive transform is technically also a NodeTransform;

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

+6
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,12 @@ export const transformVModel: DirectiveTransform = (dir, node, context) => {
6565
let runtimeDirective: VaporHelper | undefined
6666

6767
if (isComponent) {
68+
return {
69+
key: arg ? arg : createSimpleExpression('modelValue', true),
70+
value: exp,
71+
model: true,
72+
modifiers: dir.modifiers,
73+
}
6874
} else {
6975
if (dir.arg)
7076
context.options.onError(

0 commit comments

Comments
 (0)