一、v-model 的本质
v-model 本质上是一个 语法糖,用于实现:
-
父组件向子组件传值
-
子组件向父组件回传更新
在 Vue 3 中,v-model 默认等价于:
javascript
:modelValue="xxx" @update:modelValue="xxx = $event"
二、基础用法(表单元素)
1. 文本输入框
html
<input v-model="username" />
等价于:
html
<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 默认规则(强烈推荐)
子组件
javascript
<script setup>
defineProps({
modelValue: String
})
const emit = defineEmits(['update:modelValue'])
</script>
<template>
<input
:value="modelValue"
@input="emit('update:modelValue', $event.target.value)"
/>
</template>
父组件
javascript
<Child v-model="username" />
2. 等价展开写法(理解用)
html
<Child :modelValue="username" @update:modelValue="username = $event" />
四、自定义 v-model 参数(Vue 3 新特性)
1. 父组件
html
<Child v-model:title="title" />
2. 子组件
javascript
<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(非常实用)
父组件
html
<Child v-model:title="title" v-model:content="content" />
子组件
html
<script setup>
defineProps({
title: String,
content: String
})
const emit = defineEmits([
'update:title',
'update:content'
])
</script>
六、v-model 修饰符(.trim / .number 等)
1. 使用方式
html
<Child v-model:title.trim="title" />
2. 子组件接收修饰符
javascript
<script setup>
const props = defineProps({
title: String,
titleModifiers: {
default: () => ({})
}
})
</script>
3. 使用修饰符
html
if (props.titleModifiers.trim) {
value = value.trim()
}
七、在 computed 中使用 v-model(双向绑定)
javascript
const value = computed({
get() {
return props.modelValue
},
set(val) {
emit('update:modelValue', val)
}
})
模板中直接使用:
html
<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
十、完整示例(可直接复制)
父组件
html
<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
html
<script setup>
defineProps({
modelValue: String
})
const emit = defineEmits(['update:modelValue'])
</script>
<template>
<input
:value="modelValue"
@input="emit('update:modelValue', $event.target.value)"
/>
</template>