update:modelValue 是用于实现自定义组件双向数据绑定的核心机制。以下是它的用法小结:
<!-- MyInput.vue -->
<script setup>
const props = defineProps(['modelValue'])
const emit = defineEmits(['update:modelValue'])
const handleInput = (e) => {
emit('update:modelValue', e.target.value)
}
</script>
<template>
<input :value="modelValue" @input="handleInput" />
</template>
<template>
<MyInput v-model="text" />
<!-- 等价于 -->
<MyInput :modelValue="text" @update:modelValue="text = $event" />
</template>
defineModel() (Vue 3.4+ 推荐)Vue 3.4 引入了 defineModel(),简化了双向绑定的实现:
<!-- MyInput.vue -->
<script setup>
// 自动处理 props 和 emits
const model = defineModel()
// 如果需要类型检查
const model = defineModel<string>() // 指定类型
const model = defineModel({ type: String, default: '' }) // 带选项
</script>
<template>
<input v-model="model" />
</template>
<!-- UserForm.vue -->
<script setup>
defineProps({
firstName: String,
lastName: String,
age: Number
})
defineEmits(['update:firstName', 'update:lastName', 'update:age'])
</script>
<template>
<input
:value="firstName"
@input="$emit('update:firstName', $event.target.value)"
/>
<input
:value="lastName"
@input="$emit('update:lastName', $event.target.value)"
/>
<input
type="number"
:value="age"
@input="$emit('update:age', parseInt($event.target.value) || 0)"
/>
</template>
<template>
<UserForm
v-model:firstName="firstName"
v-model:lastName="lastName"
v-model:age="age"
/>
</template>
defineModel() 处理多个 v-model<!-- UserForm.vue -->
<script setup>
const firstName = defineModel('firstName')
const lastName = defineModel('lastName')
const age = defineModel('age', { type: Number, default: 0 })
</script>
<template>
<input v-model="firstName" />
<input v-model="lastName" />
<input v-model="age" type="number" />
</template>
<!-- MyInput.vue -->
<script setup>
const [model, modifiers] = defineModel({
// 处理修饰符
set(value) {
if (modifiers.trim) {
return value.trim()
}
if (modifiers.uppercase) {
return value.toUpperCase()
}
return value
}
})
</script>
<template>
<input v-model="model" />
</template>
<template>
<MyInput v-model.trim="text" />
<MyInput v-model.uppercase="text" />
</template>
<!-- ObjectPicker.vue -->
<script setup>
const props = defineProps({
modelValue: {
type: Object,
default: () => ({})
}
})
const emit = defineEmits(['update:modelValue'])
const updateField = (key, value) => {
emit('update:modelValue', {
...props.modelValue,
[key]: value
})
}
</script>
defineModel():Vue 3.4+ 优先使用,代码更简洁
明确类型定义:为 props 提供明确的类型定义
保持响应性:确保 emit 的值是响应式的
处理默认值:为可选的 modelValue 提供合适的默认值
<!-- ❌ 错误:直接修改 props -->
<script setup>
const props = defineProps(['modelValue'])
const handleInput = (e) => {
props.modelValue = e.target.value // 错误!
}
</script>
<!-- ✅ 正确:使用 emit -->
<script setup>
const props = defineProps(['modelValue'])
const emit = defineEmits(['update:modelValue'])
const handleInput = (e) => {
emit('update:modelValue', e.target.value)
}
</script>
<!-- MyInput.vue -->
<script setup lang="ts">
// 使用 defineModel
const model = defineModel<string>()
// 或者使用完整的 props/emits 定义
interface Props {
modelValue: string
}
interface Emits {
(e: 'update:modelValue', value: string): void
}
const props = defineProps<Props>()
const emit = defineEmits<Emits>()
</script>
Vue 3 的 update:modelValue 机制提供了灵活的双向数据绑定:
props + emitdefineModel()根据项目需求和 Vue 版本选择合适的实现方式。