主题
组件 v-model(组件输入绑定)
拆解
v-model -> v-model:modelValue -> :modelValue + @update:modelValue
基本用法
父组件
vue
<Child v-model="model" />子组件
ts
// Ref<string | undefined>
// const modelValue = defineModel<string>()
// Ref<string>
const modelValue = defineModel<string>({ required: true })ts
interface Props {
// modelValue?: string
modelValue: string
}
interface Emits {
'update:modelValue': [value: string]
}
const props = defineProps<Props>()
const emit = defineEmits<Emits>()多个 v-model 绑定
父组件
template
<UserName
v-model:first-name="first"
v-model:last-name="last"
/>子组件
js
const first = defineModel('firstName')
const last = defineModel('lastName')js
defineProps({
firstName: String,
lastName: String,
})
defineEmits(['update:firstName', 'update:lastName'])v-model 的修饰符
v-model.capitalize
父组件
template
<MyComponent v-model.capitalize="myText" />子组件
ts
const [model, modifiers] = defineModel<string, 'capitalize'>({
get(value: string) {
return value
},
set(value: string) {
if (modifiers.capitalize) {
return value.charAt(0).toUpperCase() + value.slice(1)
}
return value
},
})ts
interface Props {
modelValue: string
modelModifiers?: {
capitalize?: boolean
}
}
interface Emits {
'update:modelValue': [value: string]
}
const props = defineProps<Props>()
const emit = defineEmits<Emits>()
const model = computed({
get: () => props.modelValue,
set: (val: string) => {
let value = val
if (props.modelModifiers?.capitalize) {
value = val.charAt(0).toUpperCase() + val.slice(1)
}
emit('update:modelValue', value)
},
})v-model:msg.capitalize
父组件
template
<MyComponent v-model:msg.capitalize="myText" />子组件
ts
const [msg, modifiers] = defineModel<string, 'capitalize'>('msg', {
get(value: string) {
return value
},
set(value: string) {
if (modifiers.capitalize) {
return value.charAt(0).toUpperCase() + value.slice(1)
}
return value
},
})ts
interface Props {
msg: string
msgModifiers?: {
capitalize?: boolean
}
}
interface Emits {
'update:msg': [value: string]
}
const props = defineProps<Props>()
const emit = defineEmits<Emits>()
const msg = computed({
get: () => props.msg,
set: (val: string) => {
let value = val
if (props.msgModifiers?.capitalize) {
value = val.charAt(0).toUpperCase() + val.slice(1)
}
emit('update:msg', value)
},
})开发技巧
v-model 优雅继承
vue
<script setup lang="ts">
import { computed } from 'vue'
const props = defineProps<{
firstName: string
lastName: string
}>()
const emit = defineEmits<{
'update:firstName': [value: string]
'update:lastName': [value: string]
}>()
// 实现响应式的 computed
const first = computed({
get: () => props.firstName,
set: (val: string) => emit('update:firstName', val),
})
const last = computed({
get: () => props.lastName,
set: (val: string) => emit('update:lastName', val),
})
</script>
<template>
<input v-model="first" />
<input v-model="last" />
</template>vue
<script setup lang="ts">
interface Props {
firstName: string
lastName: string
}
interface Emits {
'update:firstName': [value: string]
'update:lastName': [value: string]
}
const props = defineProps<Props>()
const emit = defineEmits<Emits>()
// 处理 firstName
function onFirstInput(e: Event) {
const value = (e.target as HTMLInputElement).value
emit('update:firstName', value)
}
// 处理 lastName
function onLastInput(e: Event) {
const value = (e.target as HTMLInputElement).value
emit('update:lastName', value)
}
</script>
<template>
<a-input :value="props.firstName" @input="onFirstInput" />
<a-input :value="props.lastName" @input="onLastInput" />
</template>