v-model是 Vue 中最常用的指令之一,用于实现表单元素的双向数据绑定。它让数据与视图保持同步,大大简化了表单处理的代码量。
双向绑定包含两个方向的数据流:
<div id="app">
<input v-model="message">
<p>你输入的是:{{ message }}</p>
</div>
<script>
new Vue({
el: '#app',
data: {
message: 'Hello'
}
})
</script>
当你在输入框中修改内容时,下方的文字会实时更新。当你在代码中修改 message 时,输入框的值也会同步变化。
v-model 本质上是语法糖,它等价于:
<input
v-bind:value="message"
v-on:input="message = $event.target.value"
>
简写形式:
<input
:value="message"
@input="message = $event.target.value"
>
理解这个原理很重要,因为:
v-modelVue 会根据表单元素类型自动选择正确的属性和事件:
<input type="text" v-model="text">
<input type="password" v-model="password">
<input type="email" v-model="email">
<input type="number" v-model="number">
绑定 value 属性,监听 input 事件。
<textarea v-model="content"></textarea>
注意:在 textarea 中使用插值语法不会生效:
<!-- ❌ 错误:插值不会生效 -->
<textarea>{{ content }}</textarea>
<!-- ✅ 正确:使用 v-model -->
<textarea v-model="content"></textarea>
<!-- 单个复选框:绑定布尔值 -->
<input type="checkbox" v-model="checked">
<!-- 多个复选框:绑定数组 -->
<input type="checkbox" v-model="selected" value="apple"> 苹果
<input type="checkbox" v-model="selected" value="banana"> 香蕉
<input type="checkbox" v-model="selected" value="orange"> 橙子
绑定 checked 属性,监听 change 事件。
<input type="radio" v-model="picked" value="one"> 选项一
<input type="radio" v-model="picked" value="two"> 选项二
绑定 checked 属性,监听 change 事件。
<select v-model="selected">
<option value="a">选项 A</option>
<option value="b">选项 B</option>
</select>
绑定 value 属性,监听 change 事件。
对于单选框和复选框,可以使用静态值:
<!-- 单选框:选中时 picked = 'yes' -->
<input type="radio" v-model="picked" value="yes">
<!-- 复选框:选中时 checked = true,未选中时 checked = false -->
<input type="checkbox" v-model="checked">
<!-- 复选框:选中时 status = 'agree',未选中时 status = 'disagree' -->
<input
type="checkbox"
v-model="status"
true-value="agree"
false-value="disagree"
>
复选框默认绑定布尔值,但可以通过 true-value 和 false-value 自定义:
<div id="app">
<input
type="checkbox"
v-model="status"
true-value="yes"
false-value="no"
>
<p>状态:{{ status }}</p>
</div>
<script>
new Vue({
el: '#app',
data: {
status: 'no' // 初始值
}
})
</script>
选中时 status 为 'yes',未选中时为 'no'。
注意
true-value 和 false-value 不会影响输入框的 value 属性,只影响 v-model 绑定的值。
可以使用 v-bind 动态绑定值:
<input
type="radio"
v-model="picked"
:value="dynamicValue"
>
<input
type="checkbox"
v-model="selected"
:true-value="dynamicTrue"
:false-value="dynamicFalse"
>
<script>
new Vue({
data: {
dynamicValue: { id: 1, name: '动态值' },
dynamicTrue: 'yes',
dynamicFalse: 'no'
}
})
</script>
Vue 提供了三个常用的修饰符:
默认情况下,v-model 在 input 事件中同步输入框的值。使用 .lazy 修饰符可以改为在 change 事件后同步:
<!-- 默认:每次输入都同步 -->
<input v-model="text">
<!-- lazy:失去焦点或回车后才同步 -->
<input v-model.lazy="text">
适用场景:
自动将用户输入转换为数字类型:
<input type="number" v-model.number="age">
如果输入值无法被 parseFloat() 解析,则返回原始值。
适用场景:
自动去除首尾空格:
<input v-model.trim="text">
适用场景:
修饰符可以组合使用:
<input v-model.lazy.trim="text">
<input v-model.number.trim="price">
v-model 也可以用在自定义组件上,但需要在组件内部正确实现:
<!-- 父组件 -->
<custom-input v-model="message"></custom-input>
<!-- 子组件 -->
<template>
<input
:value="value"
@input="$emit('input', $event.target.value)"
>
</template>
<script>
export default {
props: ['value']
}
</script>
这部分内容在组件通信章节会详细讲解。
<div class="search-box">
<input
type="text"
v-model.trim="keyword"
@keyup.enter="search"
placeholder="搜索..."
>
<button @click="search">搜索</button>
</div>
<script>
new Vue({
data: {
keyword: ''
},
methods: {
search: function() {
if (!this.keyword) return
console.log('搜索:', this.keyword)
}
}
})
</script>
<div class="calculator">
<input type="number" v-model.number="a"> +
<input type="number" v-model.number="b">
= {{ a + b }}
</div>
<script>
new Vue({
data: {
a: 0,
b: 0
}
})
</script>
<form @submit.prevent="submit">
<input v-model="form.name" placeholder="姓名">
<input v-model="form.email" placeholder="邮箱">
<button type="submit">提交</button>
<button type="button" @click="reset">重置</button>
</form>
<script>
new Vue({
data: {
form: {
name: '',
email: ''
},
defaultForm: {
name: '',
email: ''
}
},
methods: {
submit: function() {
console.log('提交:', this.form)
},
reset: function() {
this.form = Object.assign({}, this.defaultForm)
}
}
})
</script>
v-model 是 Vue 表单处理的核心:
:value + @input 的组合.lazy、.number、.trim 简化常见操作v-model掌握 v-model,你就能轻松处理各种表单场景。