Skip to content

Commit da6e624

Browse files
committed
feat: component v-model update to use defineModel + defineModel modifiers & transformers
1 parent b59d839 commit da6e624

File tree

2 files changed

+243
-132
lines changed

2 files changed

+243
-132
lines changed

src/api/sfc-script-setup.md

Lines changed: 42 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -229,40 +229,60 @@ This will be compiled to equivalent runtime props `default` options. In addition
229229

230230
## defineModel() <sup class="vt-badge" data-text="3.4+" /> {#definemodel}
231231

232-
This macro can be used to declare a two-way binding prop that can be consumed via `v-model` from the parent component, and it can be declared and mutated like a ref. This will declare a prop with the same name and a corresponding `update:propName` event.
232+
This macro can be used to declare a two-way binding prop that can be consumed via `v-model` from the parent component. Example usage is also discussed in the [Component `v-model`](/guide/components/v-model) guide.
233233

234-
If the first argument is a literial string, it will be used as the prop name; Otherwise the prop name will default to `"modelValue"`. In both cases, you can also pass an additional object which will be used as the prop's options.
234+
Under the hood, this macro declares a model prop and a corresponding value update event. If the first argument is a literal string, it will be used as the prop name; Otherwise the prop name will default to `"modelValue"`. In both cases, you can also pass an additional object which can include the prop's options and the model ref's value transform options.
235235

236-
```vue
237-
<script setup>
236+
```js
237+
// declares "modelValue" prop, consumed by parent via v-model
238+
const modelValue = defineModel()
239+
// OR: declares "modelValue" prop with options
238240
const modelValue = defineModel({ type: String })
241+
242+
// emits "update:modelValue" when mutated
239243
modelValue.value = 'hello'
240244

241-
const count = defineModel('count', { default: 0 })
245+
// declares "count" prop, consumed by parent via v-model:count
246+
const count = defineModel('count')
247+
// OR: declares "count" prop with options
248+
const count = defineModel('count', { type: Number, default: 0 })
249+
242250
function inc() {
251+
// emits "update:count" when mutated
243252
count.value++
244253
}
245-
</script>
246-
247-
<template>
248-
<input v-model="modelValue" />
249-
<button @click="inc">increment</button>
250-
</template>
251254
```
252255

253-
### Local mode
256+
### Modifiers and Transformers
254257

255-
The options object can also specify an additional option, `local`. When set to `true`, the ref can be locally mutated even if the parent did not pass the matching `v-model`, essentially making the model optional.
258+
To access modifiers used with the `v-model` directive, we can destructure the return value of `defineModel()` like this:
256259

257-
```ts
258-
// local mutable model, can be mutated locally
259-
// even if the parent did not pass the matching `v-model`.
260-
const count = defineModel('count', { local: true, default: 0 })
260+
```js
261+
const [modelValue, modelModifiers] = defineModel()
262+
263+
// corresponds to v-model.trim
264+
if (modelModifiers.trim) {
265+
// ...
266+
}
267+
```
268+
269+
Usually, we need to conditionally transform the value read from or synced back to the parent when a modifier is present. We can achieve this via the `get` and `set` transformer options:
270+
271+
```js
272+
const [modelValue, modelModifiers] = defineModel({
273+
// get() omitted as it is not needed here
274+
set(value) {
275+
if (modelModifiers.trim) {
276+
return value.trim()
277+
}
278+
return value
279+
}
280+
})
261281
```
262282

263-
### Provide value type <sup class="vt-badge ts" /> {#provide-value-type}
283+
### Usage with TypeScript <sup class="vt-badge ts" /> {#usage-with-typescript}
264284

265-
Like `defineProps` and `defineEmits`, `defineModel` can also receive a type argument to specify the type of the model value:
285+
Like `defineProps` and `defineEmits`, `defineModel` can also receive type arguments to specify the types of the model value and the modifiers:
266286

267287
```ts
268288
const modelValue = defineModel<string>()
@@ -271,6 +291,9 @@ const modelValue = defineModel<string>()
271291
// default model with options, required removes possible undefined values
272292
const modelValue = defineModel<string>({ required: true })
273293
// ^? Ref<string>
294+
295+
const [modelValue, modifiers] = defineModel<string, 'trim' | 'uppercase'>()
296+
// ^? Record<'trim' | 'uppercase', true | undefined>
274297
```
275298

276299
## defineExpose() {#defineexpose}

0 commit comments

Comments
 (0)