首页 > 编程笔记

Vue v-model双向绑定表单数据详解

对于 Vue 来说,使用 v-bind 并不能解决表单域对象双向绑定的需求,为此 Vue 提供了 v-model 指令。

所谓双向绑定,就是无论是通过 input 还是通过 Vue 对象,都能修改绑定的数据对象的值。

对于数据的绑定,无论是使用插值表达式({{}})还是 v-text 指令,对于数据间的交互都是单向的,只能将 Vue 实例中的值传递给页面,页面对数据值的任何操作都无法传递给 model。

MVVM 模式最重要的一个特性,可以说实现了数据的双向绑定,而 Vue 作为一个 MVVM 框架,肯定也实现了数据的双向绑定。在 Vue 中使用内置的 v-model 指令完成数据在 View 与 Model 间的双向绑定。

可以用 v-model 指令在表单的 <input>、<textarea> 及 <select> 元素上创建双向数据绑定。它会根据控件类型自动选取正确的方法来更新元素。尽管有些神奇,但 v-model 本质上不过是语法糖。它负责监听用户的输入事件以更新数据,并对一些极端场景进行特殊处理。

v-model 会忽略所有表单元素的 value、checked、selected 特性的初始值,而总是将 Vue 实例的数据作为数据来源。这里应该通过 JavaScript 在组件的 data 选项中声明初始值。

单行文本输入框

下面讲解常见的单行文本输入框的数据双向绑定。

【实例一】绑定单行文本输入框
<input type="text" v-model="message" value="hello world">
    <p>{{message}}</p>
</div>
<!--引入Vue文件-->
<script src="https://unpkg.com/vue@next"></script>
<script>
    //创建一个应用程序实例
    const vm= Vue.createApp({
        //该函数返回数据对象
        data(){
          return{
            message:"红罗袖里分明见"
           }
        }
    //在指定的DOM元素上装载应用程序实例的根组件
    }).mount('#app');
</script>
在 Chrome 浏览器中运行程序,在输入框中输入“白玉盘中看却无”,可以看到下面的内容也发生了变化,如下图所示:


图 1 变更后效果

多行文本输入框

在多行文本输入框 textarea 标签中绑定 message 属性,代码如下:
<div id="app">
    <p>{{message}}</p>
    <textarea v-model="message"></textarea>
</div>
<!--引入Vue文件-->
<script src="https://unpkg.com/vue@next"></script>
<script>
    //创建一个应用程序实例
    const vm= Vue.createApp({
        //该函数返回数据对象
        data(){
          return{
            message:"轻衣软履步江沙"
           }
        }
    //在指定的DOM元素上装载应用程序实例的根组件
    }).mount('#app');
</script>
在 Chrome 浏览器中运行程序,在textarea标签中输入多行文本,效果如下图所示。


图 2 绑定多行文本输入框

复选框

复选框单独使用时,绑定的是布尔值,选中则值为 true,未选中则值为 false。示例代码如下。
<div id="app">
    <input type="checkbox" id="checkbox" v-model="checked">
    <label for="checkbox">{{ checked }}</label>
</div>
<!--引入Vue文件-->
<script src="https://unpkg.com/vue@next"></script>
<script>
    //创建一个应用程序实例
    const vm= Vue.createApp({
        //该函数返回数据对象
        data(){
          return{
            //默认值为false
            checked:false
           }
        }
    //在指定的DOM元素上装载应用程序实例的根组件
    }).mount('#app');
</script>
在 Chrome 浏览器中运行程序,当选中复选框后,checked 的值变为 true,效果如下图所示。


图 3 选中效果

将多个复选框绑定到同一个数组,被选中的复选框添加到数组中。示例代码如下:
<div id="app">
    <p>选择需要采购的商品:</p>
    <input type="checkbox" id="name1" value="洗衣机" v-model="checkedNames">
    <label for="name1">洗衣机</label>
    <input type="checkbox" id="name2" value="冰箱" v-model="checkedNames">
    <label for="name2">冰箱</label>
    <input type="checkbox" id="name3" value="电视机" v-model="checkedNames">
    <label for="name3">电视机</label>
    <input type="checkbox" id="name4" value="空调" v-model="checkedNames">
    <label for="name4">空调</label>
    <p><span>选中的商品:{{ checkedNames }}</span></p>
</div>
<!--引入Vue文件-->
<script src="https://unpkg.com/vue@next"></script>
<script>
    //创建一个应用程序实例
    const vm= Vue.createApp({
        //该函数返回数据对象
        data(){
          return{
           checkedNames: []   //定义空数组
           }
        }
    //在指定的DOM元素上装载应用程序实例的根组件
    }).mount('#app');
</script>
在 Chrome 浏览器中运行程序,选择多个复选框,选择的内容显示在数组中,如下图所示。


图 4 绑定多个复选框

单选按钮

单选按钮一般都有多个条件可供选择,既然是单选按钮,自然希望实现互斥效果,这个效果可以使用 v-model 指令配合单选框的 value 来实现。

例如,多个单选框绑定到同一个数组,被选中的单选框添加到数组中。
<div id="app">
    <h3>请选择本次采购的商品(单选题)</h3>
    <input type="radio" id="one" value="A" v-model="picked">
    <label for="one">A.洗衣机</label><br/>
    <input type="radio" id="two" value="B" v-model="picked">
    <label for="two">B.冰箱</label><br/>
    <input type="radio" id="three" value="C" v-model="picked">
    <label for="three">C.空调</label><br/>
    <input type="radio" id="four" value="D" v-model="picked">
    <label for="four">D. 电视机</label>
    <p><span>选择: {{ picked }}</span></p>
</div>
<!--引入Vue文件-->
<script src="https://unpkg.com/vue@next"></script>
<script>
    //创建一个应用程序实例
    const vm= Vue.createApp({
        //该函数返回数据对象
        data(){
          return{
           picked: ''
           }
        }
    //在指定的DOM元素上装载应用程序实例的根组件
    }).mount('#app');
</script>
在 Chrome 浏览器中运行程序,单击“D.电视机”单选按钮,效果如下图所示。


图 5 绑定单选按钮

选择框

接下来详细讲述如何绑定单选框、多选框和用 v-for 渲染的动态选项。

1) 单选框

不需要为 <select> 标签添加任何属性,即可实现单选。示例如下。
<div id="app">
    <h3>选择喜欢的课程</h3>
    <select v-model="selected">
        <option disabled value="">选择喜欢的课程</option>
        <option>Python开发班</option>
        <option>Java开发班</option>
        <option>前端开发班</option>
    </select>
    <span>选择的课程: {{ selected }}</span>
</div>
<!--引入Vue文件-->
<script src="https://unpkg.com/vue@next"></script>
<script>
    //创建一个应用程序实例
    const vm= Vue.createApp({
        //该函数返回数据对象
        data(){
          return{
           selected: ' '
           }
        }
    //在指定的DOM元素上装载应用程序实例的根组件
    }).mount('#app');
</script>
在 Chrome 浏览器中运行程序,在下拉选项中选择“Java开发班”,选择结果中也变成了“Java开发班”,效果如下图所示。


图 6 绑定单选框

如果 v-model 表达式的初始值未能匹配任何选项,<select> 元素将被渲染为“未选中”状态。

2) 多选框(绑定到一个数组)

为 <select> 标签添加 multiple 属性,即可实现多选。示例如下。
<div id="app">
    <h3>请选择您喜欢的课程</h3>
    <select v-model="selected" multiple style="height: 100px">
        <option disabled value="">可以选择的课程如下</option>
        <option>Java开发班</option>
        <option>Python开发班</option>
        <option>前端开发班</option>
        <option>PHP开发班</option>
    </select><br/>
    <span>选择的课程: {{ selected }}</span>
</div>
<!--引入Vue文件-->
<script src="https://unpkg.com/vue@next"></script>
<script>
    //创建一个应用程序实例
    const vm= Vue.createApp({
        //该函数返回数据对象
        data(){
          return{
           selected: []
           }
        }
    //在指定的DOM元素上装载应用程序实例的根组件
    }).mount('#app');
</script>
在 Chrome 浏览器中运行程序,按住 Ctrl 键可以选择多个选项,效果如下图所示。


图 7 绑定多选框

3) 用v-for渲染的动态选项

在实际应用场景中,<select> 标签中的 <option> 一般是通过 v-for 指令动态输出的,其中每一项的 value 或 text 都可以使用 v-bind 动态输出。

例如:
<div id="app">
    <h3>请选择您喜欢的课程</h3>
    <select v-model="selected">
        <option v-for="option in options"
v-bind:value="option.value">{{option.text}}</option>
    </select>
    <span>选择的课程: {{ selected }}</span>
</div>
<!--引入Vue文件-->
<script src="https://unpkg.com/vue@next"></script>
<script>
    //创建一个应用程序实例
    const vm = Vue.createApp({
        //该函数返回数据对象
        data(){
          return{
           selected: [],
            options:[
                { text: '课程1', value: 'Java开发班' },
                { text: '课程2', value: 'Python开发班' },
                { text: '课程3', value: '前端开发班' }
            ]
           }
        }
    }).mount('#app');
</script>
在 Chrome 浏览器中运行程序,然后在选择框中选择“课程2”,将会显示它对应的 value 值,效果如下图所示。


图 8 v-for渲染的动态选项

值绑定

对于单选按钮、复选框及选择框的选项,v-model 绑定的值通常是静态字符串(对于复选框也可以是布尔值)。但是,有时可能想把值绑定到Vue实例的一个动态属性上,这种情况可以用 v-bind 实现,并且这个属性的值可以不是字符串。

1) 复选框

在下面的示例中,true-value 和 false-value 的特性并不会影响输入控件的 value 特性,因为浏览器在提交表单时并不会包含未被选中的复选框。如果要确保表单中这两个值中的一个能够被提交,比如“yes”或“no”,则需要换用单选按钮。

例如:
<div id="app">
    <input type="checkbox" v-model="toggle" true-value="yes" false-value="no">
    <span>{{toggle}}</span>
</div>
<!--引入Vue文件-->
<script src="https://unpkg.com/vue@next"></script>
<script>
    //创建一个应用程序实例
    const vm = Vue.createApp({
        //该函数返回数据对象
        data(){
          return{
           toggle:'false'
         }
        }
    }).mount('#app');
</script>
在 Chrome 浏览器中运行程序,选择复选框的状态效果如下图所示。


图 9 选择复选框的状态

2) 单选框

首先为单选按钮绑定一个属性 date,定义属性值为“洗衣机”;然后使用 v-model 指令为单选按钮绑定 pick 属性,当单选按钮被选中后,pick 的值等于 a 的属性值。

例如:
<div id="app">
    <input type="radio"  v-model="pick" v-bind:value="date">
    <span>{{ pick}}</span>
</div>
<!--引入Vue文件-->
<script src="https://unpkg.com/vue@next"></script>
<script>
    //创建一个应用程序实例
    const vm = Vue.createApp({
        //该函数返回数据对象
        data(){
          return{
            date:'洗衣机 ',
            pick:'未选择'
         }
        }
    }).mount('#app');
</script>
在 Chrome 浏览器中运行程序,选中“洗衣机”单选按钮,将显示其 value 值,效果如下图所示。


图 10 单选框选中效果

3) 选择框的选项

在下面的示例中,定义了 4 个 option 选项,并使用 v-bind 进行绑定。
<div id="app">
    <select v-model="selected" multiple>
        <option v-bind:value="{ number: 100 }">A</option>
        <option v-bind:value="{ number: 200 }">B</option>
        <option v-bind:value="{ number: 300  }">C</option>
        <option v-bind:value="{ number: 400 }">D</option>
    </select>
    <p><span>{{ selected }}</span></p>
</div>
<!--引入Vue文件-->
<script src="https://unpkg.com/vue@next"></script>
<script>
    //创建一个应用程序实例
    const vm = Vue.createApp({
        //该函数返回数据对象
        data(){
          return{
            selected:[]
         }
        }
     }).mount('#app');
</script>
在 Chrome 浏览器中运行程序,选中 C 和 D 选项,在 p 标签中将显示相应的 number 值,如下图所示。


图 11 动态绑定选择框的选项

推荐阅读