一、v-model的本质
v-model本质上是一个语法糖,用于实现:
父组件向子组件传值
子组件向父组件回传更新
在 Vue 3 中,v-model默认等价于:
:modelValue="xxx" @update:modelValue="xxx = $event"二、基础用法(表单元素)
1. 文本输入框
<input v-model="username" />等价于:
<input :value="username" @input="username = $event.target.value" />2. 常见表单绑定
| 表单类型 | 示例 |
|---|---|
| text | <input v-model="text" /> |
| checkbox | <input type="checkbox" v-model="checked" /> |
| radio | <input type="radio" value="A" v-model="picked" /> |
| select | <select v-model="selected"> |
| textarea | <textarea v-model="msg"></textarea> |
三、组件上的v-model(核心重点)
1. Vue 3 默认规则(强烈推荐)
子组件
<script setup> defineProps({ modelValue: String }) const emit = defineEmits(['update:modelValue']) </script> <template> <input :value="modelValue" @input="emit('update:modelValue', $event.target.value)" /> </template>父组件
<Child v-model="username" />2. 等价展开写法(理解用)
<Child :modelValue="username" @update:modelValue="username = $event" />四、自定义v-model参数(Vue 3 新特性)
1. 父组件
<Child v-model:title="title" />2. 子组件
<script setup> defineProps({ title: String }) const emit = defineEmits(['update:title']) </script> <template> <input :value="title" @input="emit('update:title', $event.target.value)" /> </template>五、多个v-model(非常实用)
父组件
<Child v-model:title="title" v-model:content="content" />子组件
<script setup> defineProps({ title: String, content: String }) const emit = defineEmits([ 'update:title', 'update:content' ]) </script>六、v-model修饰符(.trim/.number等)
1. 使用方式
<Child v-model:title.trim="title" />2. 子组件接收修饰符
<script setup> const props = defineProps({ title: String, titleModifiers: { default: () => ({}) } }) </script>3. 使用修饰符
if (props.titleModifiers.trim) { value = value.trim() }七、在computed中使用v-model(双向绑定)
const value = computed({ get() { return props.modelValue }, set(val) { emit('update:modelValue', val) } })模板中直接使用:
<input v-model="value" />八、v-model与 Vue 2 的核心差异
| 项目 | Vue 2 | Vue 3 |
|---|---|---|
| 默认 prop | value | modelValue |
| 默认事件 | input | update:modelValue |
| 多 v-model | 不支持 | 支持 |
| 修饰符 | 内置 | 可自定义 |
| 语法 | 固定 | 更灵活 |
九、最佳实践(工程经验)
组件统一使用
modelValue始终通过
emit修改值避免在子组件中直接修改 props
多字段表单优先使用多个 v-model
复杂逻辑用
computed封装 v-model
十、完整示例(可直接复制)
父组件
<script setup> import { ref } from 'vue' import MyInput from './MyInput.vue' const username = ref('') </script> <template> <MyInput v-model="username" /> <p>{{ username }}</p> </template>子组件MyInput.vue
<script setup> defineProps({ modelValue: String }) const emit = defineEmits(['update:modelValue']) </script> <template> <input :value="modelValue" @input="emit('update:modelValue', $event.target.value)" /> </template>