一、核心概念
v-model 是 Vue.js 中实现双向数据绑定的指令,主要用于表单输入元素或自定义组件中。它本质上是语法糖,将 v-bind
(单向绑定)和 v-on
(事件监听)结合使用。
1.1 基本原理
- 单向绑定:
v-bind:value="message"
将数据从组件传递到 DOM。 - 事件监听:
v-on:input="message = $event.target.value"
将 DOM 的变化同步回数据。 - v-model 的等价写法:
<input v-model="message"> <!-- 等价于 --> <input :value="message" @input="message = $event.target.value">
二、基础用法
2.1 绑定到表单输入
文本输入
<template>
<input v-model="message" placeholder="输入内容">
<p>输入的内容:{{ message }}</p>
</template>
<script>
export default {
data() {
return {
message: ''
}
}
}
</script>
多行文本(textarea)
<textarea v-model="description"></textarea>
复选框(Checkbox)
- 单个复选框(绑定布尔值):
<input type="checkbox" v-model="isChecked"> <label>{{ isChecked ? '已选中' : '未选中' }}</label>
- 多个复选框(绑定数组):
<input type="checkbox" v-model="hobbies" value="读书"> <input type="checkbox" v-model="hobbies" value="运动"> <input type="checkbox" v-model="hobbies" value="音乐"> <p>爱好:{{ hobbies.join(', ') }}</p>
单选按钮(Radio)
<input type="radio" v-model="gender" value="男">
<input type="radio" v-model="gender" value="女">
<p>性别:{{ gender }}</p>
选择框(Select)
- 单选:
<select v-model="selectedFruit"> <option value="苹果">苹果</option> <option value="香蕉">香蕉</option> </select>
- 多选(绑定数组):
<select v-model="selectedFruits" multiple> <option value="苹果">苹果</option> <option value="香蕉">香蕉</option> </select>
三、高级用法
3.1 修饰符(Modifiers)
Vue 提供了多个修饰符来简化常见操作:
.lazy
- 默认在
input
事件时同步数据,使用.lazy
修饰符改为在change
事件后同步:<input v-model.lazy="message">
.number
- 自动将输入值转换为数字类型:
<input v-model.number="age">
.trim
- 自动过滤输入的首尾空格:
<input v-model.trim="username">
3.2 自定义组件中的 v-model
在自定义组件中使用 v-model
时,需要明确组件如何接收和触发更新。
Vue 2 的用法
- 组件内部通过
value
prop 接收数据,通过input
事件触发更新:<!-- 父组件 --> <custom-input v-model="searchText"></custom-input>
<!-- 子组件 CustomInput.vue --> <template> <input :value="value" @input="$emit('input', $event.target.value)"> </template> <script> export default { props: ['value'] } </script>
Vue 3 的用法
- Vue 3 支持多个
v-model
绑定,且默认使用modelValue
作为 prop,update:modelValue
作为事件:<!-- 父组件 --> <custom-input v-model="searchText"></custom-input>
<!-- 子组件 CustomInput.vue --> <template> <input :value="modelValue" @input="$emit('update:modelValue', $event.target.value)"> </template> <script> export default { props: ['modelValue'] } </script>
多个 v-model 绑定(Vue 3)
<!-- 父组件 -->
<custom-user v-model:name="userName" v-model:age="userAge"></custom-user>
<!-- 子组件 CustomUser.vue -->
<template>
<input :value="name" @input="$emit('update:name', $event.target.value)">
<input :value="age" @input="$emit('update:age', $event.target.value)">
</template>
<script>
export default {
props: ['name', 'age']
}
</script>
四、常见问题
4.1 为什么数据未同步?
- 原因:未正确声明
v-model
的 prop 或未触发事件。 - 解决方案:
- 检查子组件是否通过
props
接收数据。 - 确保通过
$emit
触发update:modelValue
事件(Vue 3)或input
事件(Vue 2)。
- 检查子组件是否通过
4.2 如何绑定非表单元素?
- 场景:需要手动控制
v-model
的更新逻辑。 - 解决方案:使用计算属性或手动监听事件:
<template> <div @click="handleClick">{{ customValue }}</div> </template> <script> export default { props: ['modelValue'], methods: { handleClick() { this.$emit('update:modelValue', '点击后的值') } } } </script>
五、最佳实践
- 优先使用原生表单元素:v-model 在表单元素上的表现最直观。
- 自定义组件时明确约定:通过
props
和$emit
定义清晰的接口。 - 合理使用修饰符:避免手动处理类型转换或空格过滤。
- Vue 2 与 Vue 3 的差异:注意 Vue 3 中
v-model
的默认 prop 和事件名称变化。
六、总结
v-model 是 Vue.js 中实现双向数据绑定的核心工具,通过简单的语法糖大幅简化了表单处理的逻辑。无论是绑定原生表单元素还是自定义组件,掌握 v-model 的用法都能显著提升开发效率。