Skip to content

Commit 69da94c

Browse files
committed
feat: add model option
1 parent 75f3a47 commit 69da94c

File tree

9 files changed

+188
-101
lines changed

9 files changed

+188
-101
lines changed

packages/compiler-sfc/__tests__/__snapshots__/compileScript.spec.ts.snap

Lines changed: 19 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -658,8 +658,8 @@ exports[`SFC compile <script setup> > defineModel() > basic usage 1`] = `
658658

659659
export default {
660660
props: {
661-
\\"modelValue\\": Object.assign({ required: true }, { required: true }),
662-
\\"count\\": { required: true },
661+
\\"modelValue\\": Object.assign({ model: true }, { required: true }),
662+
\\"count\\": { model: true },
663663
},
664664
emits: [\\"update:modelValue\\", \\"update:count\\"],
665665
setup(__props, { expose: __expose }) {
@@ -679,7 +679,7 @@ exports[`SFC compile <script setup> > defineModel() > w/ array props 1`] = `
679679

680680
export default {
681681
props: _mergeModels(['foo', 'bar'], {
682-
\\"count\\": { required: true },
682+
\\"count\\": { model: true },
683683
}),
684684
emits: [\\"update:count\\"],
685685
setup(__props, { expose: __expose }) {
@@ -699,7 +699,7 @@ exports[`SFC compile <script setup> > defineModel() > w/ defineProps and defineE
699699

700700
export default {
701701
props: _mergeModels({ foo: String }, {
702-
\\"modelValue\\": Object.assign({ required: true }, { default: 0 }),
702+
\\"modelValue\\": Object.assign({ model: true }, { default: 0 }),
703703
}),
704704
emits: _mergeModels(['change'], [\\"update:modelValue\\"]),
705705
setup(__props, { expose: __expose }) {
@@ -1647,9 +1647,9 @@ exports[`SFC compile <script setup> > with TypeScript > defineModel() > basic us
16471647

16481648
export default /*#__PURE__*/_defineComponent({
16491649
props: {
1650-
\\"modelValue\\": { type: [Boolean, String], required: true },
1651-
\\"count\\": { type: Number, required: true },
1652-
\\"disabled\\": { type: Number, required: true, ...{ required: false } },
1650+
\\"modelValue\\": { model: true, type: [Boolean, String] },
1651+
\\"count\\": { model: true, type: Number },
1652+
\\"disabled\\": { model: true, type: Number, ...{ required: false } },
16531653
},
16541654
emits: [\\"update:modelValue\\", \\"update:count\\", \\"update:disabled\\"],
16551655
setup(__props, { expose: __expose }) {
@@ -1671,10 +1671,10 @@ exports[`SFC compile <script setup> > with TypeScript > defineModel() > w/ produ
16711671
export default /*#__PURE__*/_defineComponent({
16721672
props: {
16731673
\\"modelValue\\": Boolean,
1674-
\\"fn\\": { },
1675-
\\"fnWithDefault\\": { type: Function, ...{ default: () => null } },
1676-
\\"str\\": { },
1677-
\\"optional\\": { required: false },
1674+
\\"fn\\": { model: true },
1675+
\\"fnWithDefault\\": { model: true, type: Function, ...{ default: () => null } },
1676+
\\"str\\": { model: true },
1677+
\\"optional\\": { model: true, ...{ required: false } },
16781678
},
16791679
emits: [\\"update:modelValue\\", \\"update:fn\\", \\"update:fnWithDefault\\", \\"update:str\\", \\"update:optional\\"],
16801680
setup(__props, { expose: __expose }) {
@@ -2054,10 +2054,10 @@ import { defaults } from './foo'
20542054

20552055
export default /*#__PURE__*/_defineComponent({
20562056
props: _mergeDefaults({
2057-
foo: { type: Function },
2058-
bar: { type: Boolean },
2059-
baz: { type: [Boolean, Function] },
2060-
qux: null
2057+
foo: { type: Function, required: true },
2058+
bar: { type: Boolean, required: true },
2059+
baz: { type: [Boolean, Function], required: true },
2060+
qux: { required: true }
20612061
}, { ...defaults }),
20622062
setup(__props: any, { expose: __expose }) {
20632063
__expose();
@@ -2159,10 +2159,10 @@ exports[`SFC compile <script setup> > with TypeScript > withDefaults (static) w/
21592159

21602160
export default /*#__PURE__*/_defineComponent({
21612161
props: {
2162-
foo: null,
2163-
bar: { type: Boolean },
2164-
baz: { type: [Boolean, Function], default: true },
2165-
qux: { default: 'hi' }
2162+
foo: { required: true },
2163+
bar: { type: Boolean, required: true },
2164+
baz: { type: [Boolean, Function], required: true, default: true },
2165+
qux: { required: true, default: 'hi' }
21662166
},
21672167
setup(__props: any, { expose: __expose }) {
21682168
__expose();

packages/compiler-sfc/__tests__/__snapshots__/compileScriptPropsDestructure.spec.ts.snap

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -121,12 +121,12 @@ exports[`sfc props transform > default values w/ type declaration, prod mode 1`]
121121
122122
export default /*#__PURE__*/_defineComponent({
123123
props: {
124-
foo: { default: 1 },
125-
bar: { default: () => ({}) },
126-
baz: null,
127-
boola: { type: Boolean },
128-
boolb: { type: [Boolean, Number] },
129-
func: { type: Function, default: () => {} }
124+
foo: { required: false, default: 1 },
125+
bar: { required: false, default: () => ({}) },
126+
baz: { required: false },
127+
boola: { type: Boolean, required: false },
128+
boolb: { type: [Boolean, Number], required: false },
129+
func: { type: Function, required: false, default: () => {} }
130130
},
131131
setup(__props: any) {
132132

packages/compiler-sfc/__tests__/compileScript.spec.ts

Lines changed: 21 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -378,9 +378,9 @@ defineExpose({ foo: 123 })
378378
)
379379
assertCode(content)
380380
expect(content).toMatch(
381-
'"modelValue": Object.assign({ required: true }, { required: true }),'
381+
'"modelValue": Object.assign({ model: true }, { required: true }),'
382382
)
383-
expect(content).toMatch('"count": { required: true },')
383+
expect(content).toMatch('"count": { model: true },')
384384
expect(content).toMatch('emits: ["update:modelValue", "update:count"],')
385385
expect(content).toMatch(`const modelValue = _useModel("modelValue")`)
386386
expect(content).toMatch(`const c = _useModel("count")`)
@@ -408,7 +408,7 @@ defineExpose({ foo: 123 })
408408
assertCode(content)
409409
expect(content).toMatch(`props: _mergeModels({ foo: String }`)
410410
expect(content).toMatch(
411-
`"modelValue": Object.assign({ required: true }, { default: 0 })`
411+
`"modelValue": Object.assign({ model: true }, { default: 0 })`
412412
)
413413
expect(content).toMatch(`const count = _useModel("modelValue")`)
414414
expect(content).not.toMatch('defineModel')
@@ -431,7 +431,7 @@ defineExpose({ foo: 123 })
431431
)
432432
assertCode(content)
433433
expect(content).toMatch(`_mergeModels(['foo', 'bar'], {`)
434-
expect(content).toMatch(`"count": { required: true }`)
434+
expect(content).toMatch(`"count": { model: true }`)
435435
expect(content).toMatch(`const count = _useModel("count")`)
436436
expect(content).not.toMatch('defineModel')
437437
expect(bindings).toStrictEqual({
@@ -1510,12 +1510,12 @@ const emit = defineEmits(['a', 'b'])
15101510
expect(content).toMatch(`const props = __props`)
15111511

15121512
// foo has no default value, the Function can be dropped
1513-
expect(content).toMatch(`foo: null`)
1514-
expect(content).toMatch(`bar: { type: Boolean }`)
1513+
expect(content).toMatch(`foo: { required: true }`)
1514+
expect(content).toMatch(`bar: { type: Boolean, required: true }`)
15151515
expect(content).toMatch(
1516-
`baz: { type: [Boolean, Function], default: true }`
1516+
`baz: { type: [Boolean, Function], required: true, default: true }`
15171517
)
1518-
expect(content).toMatch(`qux: { default: 'hi' }`)
1518+
expect(content).toMatch(`qux: { required: true, default: 'hi' }`)
15191519
})
15201520

15211521
test('withDefaults (dynamic)', () => {
@@ -1585,10 +1585,10 @@ const emit = defineEmits(['a', 'b'])
15851585
expect(content).toMatch(
15861586
`
15871587
_mergeDefaults({
1588-
foo: { type: Function },
1589-
bar: { type: Boolean },
1590-
baz: { type: [Boolean, Function] },
1591-
qux: null
1588+
foo: { type: Function, required: true },
1589+
bar: { type: Boolean, required: true },
1590+
baz: { type: [Boolean, Function], required: true },
1591+
qux: { required: true }
15921592
}, { ...defaults })`.trim()
15931593
)
15941594
})
@@ -1801,11 +1801,11 @@ const emit = defineEmits(['a', 'b'])
18011801
)
18021802
assertCode(content)
18031803
expect(content).toMatch(
1804-
'"modelValue": { type: [Boolean, String], required: true }'
1804+
'"modelValue": { model: true, type: [Boolean, String] }'
18051805
)
1806-
expect(content).toMatch('"count": { type: Number, required: true }')
1806+
expect(content).toMatch('"count": { model: true, type: Number }')
18071807
expect(content).toMatch(
1808-
'"disabled": { type: Number, required: true, ...{ required: false } },'
1808+
'"disabled": { model: true, type: Number, ...{ required: false } },'
18091809
)
18101810
expect(content).toMatch(
18111811
'emits: ["update:modelValue", "update:count", "update:disabled"]'
@@ -1838,12 +1838,14 @@ const emit = defineEmits(['a', 'b'])
18381838
)
18391839
assertCode(content)
18401840
expect(content).toMatch('"modelValue": Boolean')
1841-
expect(content).toMatch('"fn": { }')
1841+
expect(content).toMatch('"fn": { model: true }')
18421842
expect(content).toMatch(
1843-
'"fnWithDefault": { type: Function, ...{ default: () => null } },'
1843+
'"fnWithDefault": { model: true, type: Function, ...{ default: () => null } },'
1844+
)
1845+
expect(content).toMatch('"str": { model: true }')
1846+
expect(content).toMatch(
1847+
'"optional": { model: true, ...{ required: false } }'
18441848
)
1845-
expect(content).toMatch('"str": { }')
1846-
expect(content).toMatch('"optional": { required: false }')
18471849
expect(content).toMatch(
18481850
'emits: ["update:modelValue", "update:fn", "update:fnWithDefault", "update:str", "update:optional"]'
18491851
)

packages/compiler-sfc/__tests__/compileScriptPropsDestructure.spec.ts

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -133,15 +133,15 @@ describe('sfc props transform', () => {
133133
)
134134
// literals can be used as-is, non-literals are always returned from a
135135
// function
136+
assertCode(content)
136137
expect(content).toMatch(`props: {
137-
foo: { default: 1 },
138-
bar: { default: () => ({}) },
139-
baz: null,
140-
boola: { type: Boolean },
141-
boolb: { type: [Boolean, Number] },
142-
func: { type: Function, default: () => {} }
138+
foo: { required: false, default: 1 },
139+
bar: { required: false, default: () => ({}) },
140+
baz: { required: false },
141+
boola: { type: Boolean, required: false },
142+
boolb: { type: [Boolean, Number], required: false },
143+
func: { type: Function, required: false, default: () => {} }
143144
}`)
144-
assertCode(content)
145145
})
146146

147147
test('aliasing', () => {

packages/compiler-sfc/src/compileScript.ts

Lines changed: 11 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -127,7 +127,7 @@ export interface SFCScriptCompileOptions {
127127
*/
128128
hoistStatic?: boolean
129129
/**
130-
* (Experimental) Enable macro `defineModel`
130+
* (**Experimental**) Enable macro `defineModel`
131131
*/
132132
defineModel?: boolean
133133
}
@@ -997,12 +997,16 @@ export function compileScript(
997997
// #4783 for boolean, should keep the type
998998
// #7111 for function, if default value exists or it's not static, should keep it
999999
// in production
1000-
return `${key}: { type: ${toRuntimeTypeString(type)}${
1000+
return `${key}: { type: ${toRuntimeTypeString(
1001+
type
1002+
)}, required: ${required}${
10011003
defaultString ? `, ${defaultString}` : ``
10021004
} }`
10031005
} else {
10041006
// production: checks are useless
1005-
return `${key}: ${defaultString ? `{ ${defaultString} }` : 'null'}`
1007+
return `${key}: ${`{ required: ${required}${
1008+
defaultString ? `, ${defaultString}` : ``
1009+
} }`}`
10061010
}
10071011
})
10081012
.join(',\n ')}\n }`
@@ -1035,21 +1039,18 @@ export function compileScript(
10351039
undefined
10361040

10371041
let decl: string
1038-
10391042
if (runtimeType && isProd && !options) {
10401043
decl = runtimeType
10411044
} else {
1042-
const pairs: string[] = []
1043-
if (runtimeType) pairs.push(`type: ${runtimeType}`)
1044-
if (!isProd) pairs.push('required: true')
1045-
decl = pairs.join(', ')
1045+
decl = 'model: true'
1046+
if (runtimeType) decl += `, type: ${runtimeType}`
10461047

1047-
if (decl && options) {
1048+
if (options) {
10481049
decl = isTS
10491050
? `{ ${decl}, ...${options} }`
10501051
: `Object.assign({ ${decl} }, ${options})`
10511052
} else {
1052-
decl = options || `{ ${decl} }`
1053+
decl = `{ ${decl} }`
10531054
}
10541055
}
10551056

0 commit comments

Comments
 (0)