表单元素绑定
1、文本框绑定
v-model会根据控件类型自动选取正确的方法来更新元素。在表单中,最基本的表单控件类型是文本框。文本框分为单行文本框和多行文本框。下面介绍将文本框中输入
1.1、单行文本框
单行文本框的作用是输入单行文本。例如,应用v-model指令将单行文本框和定义的数据进行绑定。代码如下:
html
<div id="app">
<input type="text" v-model="text">
<p>{{text}}</p>
</div>
<script src="https://unpkg.com/vue@3/dist/vue.global.js"></script>
<script type="text/javascript">
const vm = Vue.createApp({
data() {
return {
text: '山不在高,有仙则名'
}
}
}).mount('#app');
</script>

运行程序,结果如图所示。在单行文本框中输入新的内容,下面的内容也会随着变化。
上述代码中,应用v-model指令将单行文本框的值和Vue实例中的text属性值进行了绑定。当单行文本框中的内容发生变化时,text属性值也会自动更新。
示例:搜索商品信息。
定义一个单行文本框和一个商品列表,在单行文本框中输入搜索关键字,下方展示搜索到的指定商品信息,代码如下:
html
<div id="app">
<div class="search">
<input type="text" v-model="searchStr" placeholder="请输入搜索内容">
</div>
<div>
<div class="item" v-for="goods in results">
<img :src="goods.image" style="height: 50px; width: 50px;">
<span>{{goods.name}}</span>
</div>
</div>
</div>
<script src="https://unpkg.com/vue@3/dist/vue.global.js"></script>
<script type="text/javascript">
const vm = Vue.createApp({
data() {
return {
searchStr: '',
goods: [
{name: '爆裂飞车', image: 'images/1.jpg'},
{name: '个性水杯', image: 'images/2.jpg'},
{name: '调料盒', image: 'images/3.jpg'},
{name: '吸油烟机', image: 'images/3.jpg'},
{name: '无线蓝牙耳机', image: 'images/4.jpg'},
{name: '自拍杆', image: 'images/4.jpg'},
]
}
},
computed: {
results: function() {
let goods = this.goods;
if(this.searchStr === '') {
return goods;
}
let searchStr = this.searchStr.trim().toLowerCase();
goods = goods.filter((ele)=> {
if(ele.name.toLowerCase().indexOf(searchStr) !== -1) {
return ele;
}
});
return goods;
}
}
}).mount('#app');
</script>


1.2、多行文本框
多行文本框也叫文本域。例如,应用v-model指令将文本域和定义的数据进行绑定。代码如下:
html
<div id="app">
<textarea rows="6" v-model="text"></textarea>
<p style="white-space: pre;">{{text}}</p>
</div>
<script src="https://unpkg.com/vue@3/dist/vue.global.js"></script>
<script type="text/javascript">
const vm = Vue.createApp({
data() {
return {
text: '横看成岭侧成峰'
}
},
}).mount('#app');
</script>
运行程序,结果如图所示。在文本域中输入多行文本,下面的内容也会随着变化。

示例:统计输入的文章字数。
在添加文章的表单中,对用户输入的文章字数进行统计,在多行文本框右侧提示用户已经输入的字数,代码如下:
html
<div id="app">
<form id="form" name="form">
<div class="title">添加文章</div>
<div class="one">
<label>文章标题:</label>
<input name="title" id="title" type="text">
</div>
<div class="one">
<label>文章内容</label>
<textarea cols="26" rows="6" v-model="message" @keyup="count"></textarea>
<span>{{tips}}</span>
</div>
<div class="two">
<input type="button" value="添加">
<input type="reset" value="重置">
</div>
</form>
</div>
<script src="https://unpkg.com/vue@3/dist/vue.global.js"></script>
<script type="text/javascript">
const vm = Vue.createApp({
data() {
return {
message: '',
tips: ''
}
},
methods: {
count: function() {
let len = this.message.length;
this.tips = '当前字数:' + len;
}
}
}).mount('#app');
</script>

2、复选框绑定
为复选框进行数据绑定有两种情况,一种是将数据绑定到单个复选框,另一种是将数据绑定到多个复选框。下面分别介绍这两种情况。
2.1、单个复选框
如果将数据绑定到单个复选框,那么应用v-model指令绑定的就是一个布尔值。示例代码如下:
html
<div id="app">
<input type="checkbox" id="check" v-model="checked">
<label for="check">是否选中:{{checked}}</label>
</div>
<script src="https://unpkg.com/vue@3/dist/vue.global.js"></script>
<script type="text/javascript">
const vm = Vue.createApp({
data() {
return {
checked: false
}
}
}).mount('#app');
</script>
运行上述代码,当选中复选框时,应用v-model指令绑定的checked属性值为true,否则该属性值为false,而label元素中的值也会随之发生变化。

示例:切换注册按钮的状态。
用户在进行注册时,首先需要同意相关的注册协议,才能进一步实现注册。当用户未选中注册协议复选框时,"注册"按钮为禁用状态;当用户选中注册协议复选框时,"注册"按钮为启用状态。代码如下:
html
<style>
.light{
background-color: green;
cursor: pointer ;
}
.dark{
background-color: #BBBBBB;
cursor: auto;
}
</style>
<div id="app">
<div class="middle-box">
<span>
<a class="active">注册</a>
</span>
<form name="form" autocomplete="off">
<div class="form-group">
<label for="name">用户名:</label>
<input id="name" type="text" class="form-control" placeholder="请输入用户名">
</div>
<div class="form-group">
<label for="password">密码</label>
<input id="password" type="password" class="form-control" placeholder="请输入密码">
</div>
<div class="form-group">
<label for="tel">手机号:</label>
<input id="tel" type="text" class="form-control" placeholder="请输入手机号">
</div>
<div class="form-group">
<label for="code">验证码:</label>
<input id="code" type="text" class="form-control" placeholder="请输入验证码">
<span class="tip">获取验证码</span>
</div>
<div class="form-group">
<div class="agreement">
<input type="checkbox" v-model="isChecked" @click="check">阅读并同意
<a href="#">《注册协议》</a>
</div>
</div>
<div>
<button type="button" class="btn-primary" :class="styleObj" v-bind:disabled="isDisabled">
注册
</button>
</div>
</form>
</div>
</div>
<script src="https://unpkg.com/vue@3/dist/vue.global.js"></script>
<script type="text/javascript">
const vm = Vue.createApp({
data() {
return {
isChecked: false,
isDisabled: true,
isLight: false,
isDark: true
}
},
methods: {
check: function() {
this.isChecked = !this.isChecked;
this.isDisabled = !this.isDisabled;
this.isLight = !this.isLight;
this.isDark = !this.isDark;
}
},
computed: {
styleObj: function() {
return {
light: this.isLight,
dark: this.isDark
}
}
}
}).mount('#app');
</script>
运行实例,默认状态下,注册协议复选框未被选中,"注册"按钮为禁用状态,结果如图所示。

选中注册协议复选框,"注册"按钮变为可用状态,结果如图所示。

2.2、多个复选框
如果将数据绑定到多个复选框,那么应用v-model指令绑定的就是一个数组。示例代码如下:
html
<div id="app">
<p>请选择您喜欢的电影类型:</p>
<input type="checkbox" id="action" value="动作片" v-model="like">
<label for="action">动作片</label>
<input type="checkbox" id="action" value="爱情片" v-model="like">
<label for="action">爱情片</label>
<input type="checkbox" id="action" value="枪战片" v-model="like">
<label for="action">枪战片</label>
<input type="checkbox" id="action" value="科幻片" v-model="like">
<label for="action">科幻片</label>
<input type="checkbox" id="action" value="动漫" v-model="like">
<label for="action">动漫</label>
<p>您喜欢的电影类型:{{like}}</p>
</div>
<script src="https://unpkg.com/vue@3/dist/vue.global.js"></script>
<script type="text/javascript">
const vm = Vue.createApp({
data() {
return {
like: []
}
},
}).mount('#app');
</script>
上述代码中,应用v-model指令将多个复选框和同一个数组like进行绑定,当选中某个复选框时,该复选框的value属性值会存入like数组中。当取消选中某个复选框时,该复选框的值会从like数组中移除。运行结果如图所示。

3、单选按钮绑定
当某个单选按钮被选中时,v-model绑定的属性值会被赋值为该单选按钮的value属性值。示例代码如下:
html
<div id="app">
请选择性别:
<input type="radio" id="male" value="男" v-model="sex">
<label for="male">男</label>
<input type="radio" id="female" value="女" v-model="sex">
<label for="male">男</label>
<p>你的性别:{{sex}}</p>
</div>
<script src="https://unpkg.com/vue@3/dist/vue.global.js"></script>
<script type="text/javascript">
const vm = Vue.createApp({
data() {
return {
sex: ''
}
},
}).mount('#app');
</script>

示例:应用单选按钮实现选择题。
应用单选按钮实现一个选择题。如果未选择答案,则直接单击"提交答案"按钮时提示"请选择答案",如果选择的选项不正确,则单击"提交答案"按钮时提示"答案不正确",否则提示"答案正确"。代码如下:
html
<div id="app">
<form name="myform">
电影《变相怪杰》的主演是?
<p>
<input type="radio" v-model="star" value="布拉德皮特">布拉德皮特
<input type="radio" v-model="star" value="亚当桑德斯">亚当桑德斯
<input type="radio" v-model="star" value="金凯瑞">金凯瑞
<input type="radio" v-model="star" value="杰夫丹尼尔斯">杰夫丹尼尔斯
</p>
<input type="button" value="提交答案" @click="show">
</form><br>
<div>{{message}}</div>
</div>
<script src="https://unpkg.com/vue@3/dist/vue.global.js"></script>
<script type="text/javascript">
const vm = Vue.createApp({
data() {
return {
star: '',
message: ''
}
},
methods: {
show() {
if(this.star === '') {
this.message = '请选择答案!';
} else if(this.star === '金凯瑞') {
this.message = '答案正确';
} else {
this.message = '答案不正确';
}
}
}
}).mount('#app');
</script>

4、 下拉列表框绑定
下拉菜单和复选框一样也分为单选和多选两种,所以应用v-model指令将数据绑定到下拉菜单也分为两种不同的情况。
4.1、单选列表框
在只提供单选的下拉菜单中,当选择某个选项时,如果为该选项设置了value值,则v-model绑定的属性值会被赋值为该选项的value值;如果未设置value值,则v-model绑定的属性值会被赋值为显示在该选项中的文本。示例代码如下:
html
<div id="app">
<label for="book">请选择书籍类型:</label>
<select id="book" v-model="booktype">
<option value="">请选择</option>
<option>文学小说</option>
<option>教育培训</option>
<option>人文社科</option>
<option>学习用书</option>
<option>少儿图书</option>
</select>
<p>书籍类型:{{booktype}}</p>
</div>
<script src="https://unpkg.com/vue@3/dist/vue.global.js"></script>
<script type="text/javascript">
const vm = Vue.createApp({
data() {
return {
booktype: ''
}
},
}).mount('#app');
</script>

有时需要通过v-for指令动态地生成下拉菜单中的option选项,再应用v-model指令对生成的下拉菜单进行绑定。示例代码如下:
html
<div id="app">
<p>诗句:"忽如一夜春风来,千树万树梨花开。"描写的是哪个季节的景色?</p>
<select v-model="answer" @change="select">
<option value="">请选择答案</option>
<option v-for="item in items" :value="item.value">{{item.text}}</option>
</select>
<p v-if="isshow">你的答案:{{answer}},答案{{result}}</p>
</div>
<script src="https://unpkg.com/vue@3/dist/vue.global.js"></script>
<script type="text/javascript">
const vm = Vue.createApp({
data() {
return {
answer: '',
items: [
{text: 'A, 春天', value: 'A'},
{text: 'B, 夏天', value: 'B'},
{text: 'C, 秋天', value: 'C'},
{text: 'D, 冬天', value: 'D'},
],
isshow: false,
result: ''
}
},
methods: {
select: function() {
this.isshow = this.answer !== '' ? true : false;
this.result = this.answer === 'D' ? '正确' : '不正确';
}
}
}).mount('#app');
</script>

示例:更换页面主题。
设置一个选择页面主题的下拉菜单,当选择某个选项时可以更换主题,实现文档的背景色和文本颜色变换的功能。代码如下:
html
<div id="app">
<form name="form">
<select v-model="theme" @change="changeTheme">
<option v-for="item in items" :value="item.value">{{item.text}}</option>
</select>
</form>
<div class="top">
苏轼《题西林壁》
</div>
<div class="content">
横看成岭侧成峰,
远近高低各不同。
不识庐山真面目,
只缘身在此山中。
</div>
</div>
<script src="https://unpkg.com/vue@3/dist/vue.global.js"></script>
<script type="text/javascript">
const vm = Vue.createApp({
data() {
return {
theme: '',
items: [
{value: '', text: '请选择主题'},
{value: 'black', text: '黑色主题'},
{value: 'blue', text: '蓝色主题'},
{value: 'green', text: '绿色主题'},
],
themeArr: [
{bgcolor: '', color: ''},
{bgcolor: 'black', color: 'yellow'},
{bgcolor: 'blue', color: 'orange'},
{bgcolor: 'green', color: 'white'},
]
}
},
methods: {
changeTheme: function() {
for(let i = 0; i < this.items.length; i++) {
if(this.theme === this.items[i].value) {
document.body.style.backgroundColor = this.themeArr[i].bgcolor;
document.body.style.color = this.themeArr[i].color;
}
}
}
}
}).mount('#app');
</script>

4.2、多选列表框
如果为select元素设置了multiple属性,那么菜单中的选项就可以进行多选。在进行多选时,应用v-model指令绑定的属性值是一个数组。示例代码如下:
html
<div id="app">
<p>请选择课程:</p>
<select v-model="course" multiple="multiple" size="6">
<option>高等数学</option>
<option>计算机基础</option>
<option>自动控制</option>
<option>传感器</option>
<option>机械制图</option>
<option>数据库设计</option>
</select>
<p>选择的类型:{{course}}</p>
</div>
<script src="https://unpkg.com/vue@3/dist/vue.global.js"></script>
<script type="text/javascript">
const vm = Vue.createApp({
data() {
return {
course: []
}
},
methods: {
changeTheme: function() {
for(let i = 0; i < this.items.length; i++) {
if(this.theme === this.items[i].value) {
document.body.style.backgroundColor = this.themeArr[i].bgcolor;
document.body.style.color = this.themeArr[i].color;
}
}
}
}
}).mount('#app');
</script>
上述代码中,应用v-model指令将select元素绑定到数组course,当选择某个选项时,该选项中的文本会存入course数组中。当取消选择某个选项时,该选项中的文本会从course数组中移除。运行结果如图所示。

示例:选择电器种类。
制作一个简单的选择电器种类的程序,用户可以在"可选电器种类"列表框和"已选电器种类"列表框之间进行选项的移动。代码如下:
html
<style>
#app{
display: flex;
}
.left{
width: 100px;
}
.middle{
float: left;
width: 100px;
display: flex;
align-items: center;
}
.right{
float: left;
width: 100px;
}
</style>
<div id="app">
<div class="left">
<span>可选电器种类</span>
<select size="6" multiple="multiple" v-model="appliance">
<option v-for="value in appliancelist" :value="value">{{value}}</option>
</select>
</div>
<div class="middle">
<input type="button" value=">>" @click="toMyappliance">
<input type="button" value="<<" @click="toappliance">
</div>
<div class="right">
<span>已选电器种类</span>
<select size="6" multiple="multiple" v-model="myappliance">
<option v-for="value in myappliancelist" :value="value">{{value}}</option>
</select>
</div>
</div>
<script src="https://unpkg.com/vue@3/dist/vue.global.js"></script>
<script type="text/javascript">
const vm = Vue.createApp({
data() {
return {
//所有电器种类
appliancelist: ['电视', '空调', '洗衣机', '冰箱', '厨卫大电', '厨房小电'],
//已选电器种类
myappliancelist: [],
//可选电器种类列表中的选项
appliance: [],
//已选电器种类列表中的选项
myappliance: []
}
},
methods: {
toMyappliance: function() {
for(let i = 0; i < this.appliance.length; i++) {
//添加到已选电器种类列表
this.myappliancelist.push(this.appliance[i]);
//获取选项索引
let index = this.appliancelist.indexOf(this.appliance[i]);
//从可选电器种类列表移除
this.appliancelist.splice(index, 1);
}
this.appliance = [];
},
toappliance: function() {
for(let i = 0; i < this.myappliance.length; i++) {
//添加到可选电器种类列表
this.appliancelist.push(this.myappliance[i]);
//获取选项索引
let index = this.myappliancelist.indexOf(this.myappliance[i]);
//从已选电器种类列表移除
this.myappliancelist(index, 1);
}
this.myappliance = [];
}
}
}).mount('#app');
</script>

5、值绑定
通常情况下,对于单选按钮、复选框以及下拉菜单中的选项,v-model绑定的值通常是静态字符串(单个复选框是布尔值)。但有时需要把值绑定到Vue实例的一个动态属性上,这时可以应用v-bind来实现,并且该属性值可以不是字符串,例如它可以是数值、对象、数组等。下面介绍在单选按钮、复选框以及下拉菜单中如何将值绑定到一个动态属性上。
5.1、单选按钮
例如,页面中有两个用来选择是否喜欢旅游的单选按钮,将单选按钮的值绑定到一个动态属性上。代码如下:
html
<div id="app">
<p>你喜欢旅游吗?</p>
<input type="radio" id="is" :value="items.is" v-model="like">
<label for="is">喜欢</label>
<input type="radio" id="no" :value="items.no" v-model="like">
<label for="is">不喜欢</label>
<p>你的选择是:{{like}}</p>
</div>
<script src="https://unpkg.com/vue@3/dist/vue.global.js"></script>
<script type="text/javascript">
const vm = Vue.createApp({
data() {
return {
like: '',
items: {is: '喜欢', no: '不喜欢'}
}
}
}).mount('#app');
</script>

5.2、复选框
在单个复选框中,应用true-value和false-value属性可以将复选框的值绑定到动态属性上。示例代码如下:
html
<div id="app">
<input type="checkbox" id="check" v-model="toggle" :true-value="yes" :false-value="no">
<label for="check">{{toggle}}</label>
</div>
<script src="https://unpkg.com/vue@3/dist/vue.global.js"></script>
<script type="text/javascript">
const vm = Vue.createApp({
data() {
return {
toggle: '',
yes: '复选框被选中',
no: '复选框未被选中'
}
}
}).mount('#app');
</script>

在多个复选框中,将复选框的值绑定到动态属性上需要使用v-bind指令。例如,通过复选框选择酒店类型,选择后输出选中的选项。代码如下:
html
<div id="app">
<p>请选择你喜欢的酒店类型:</p>
<input type="checkbox" :value="hotels[0]" v-model="hotel">
<label>{{hotels[0]}}</label>
<input type="checkbox" :value="hotels[1]" v-model="hotel">
<label>{{hotels[1]}}</label>
<input type="checkbox" :value="hotels[2]" v-model="hotel">
<label>{{hotels[2]}}</label>
<input type="checkbox" :value="hotels[3]" v-model="hotel">
<label>{{hotels[3]}}</label>
<input type="checkbox" :value="hotels[4]" v-model="hotel">
<label>{{hotels[4]}}</label>
<input type="checkbox" :value="hotels[5]" v-model="hotel">
<label>{{hotels[5]}}</label>
<p>选择的酒店类型:{{hotel.join('、')}}</p>
</div>
<script src="https://unpkg.com/vue@3/dist/vue.global.js"></script>
<script type="text/javascript">
const vm = Vue.createApp({
data() {
return {
hotels: ['商务型酒店', '主题酒店', '连锁品牌', '酒店式公寓', '家庭旅馆', '客栈'],
hotel: []
}
}
}).mount('#app');
</script>

5.3、下拉列表框
例如,定义一个用来选择音乐类型的下拉菜单,在下拉菜单中将值绑定到一个动态属性上。代码如下:
html
<div id="app">
<span>请选择音乐类型:</span>
<select v-model="type">
<option :value="types[0]">{{types[0]}}</option>
<option :value="types[1]">{{types[1]}}</option>
<option :value="types[2]">{{types[2]}}</option>
<option :value="types[3]">{{types[3]}}</option>
</select>
<p>选择的音乐类型:{{type}}</p>
</div>
<script src="https://unpkg.com/vue@3/dist/vue.global.js"></script>
<script type="text/javascript">
const vm = Vue.createApp({
data() {
return {
types: ['流行音乐', '民族音乐', '摇滚音乐', '古典音乐'],
type: '流行音乐'
}
}
}).mount('#app');
</script>

6、修饰符的使用
Vue.js为v-model指令提供了一些修饰符,通过这些修饰符可以处理某些常规操作。这些修饰符的说明如下。
6.1、lazy
默认情况下,应用v-model指令将文本框的值与数据进行同步时使用的是input事件。如果添加了lazy修饰符,就可以转变为使用change事件进行同步。示例代码如下:
html
<div id="app">
<input v-model.lazy="message" placeholder="请输入内容">
<p>{{message}}</p>
</div>
<script src="https://unpkg.com/vue@3/dist/vue.global.js"></script>
<script type="text/javascript">
const vm = Vue.createApp({
data() {
return {
message: ''
}
}
}).mount('#app');
</script>
运行上述代码,当触发文本框的change事件后,才会使输出的内容和文本框中输入的内容同步。运行结果如图所示。

6.2、number
通过在v-model指令中使用number修饰符,可以自动将用户输入的内容转换为数值类型。如果转换结果为NaN,则返回用户输入的原始值。示例代码如下:
html
<div id="app">
<input v-model.number="message" placeholder="请输入内容">
<p>{{message}}</p>
</div>
<script src="https://unpkg.com/vue@3/dist/vue.global.js"></script>
<script type="text/javascript">
const vm = Vue.createApp({
data() {
return {
message: ''
}
}
}).mount('#app');
</script>

6.3、trim
通过为v-model指令添加trim修饰符可以自动过滤用户输入的字符串的首尾空格。示例代码如下:
html
<div id="app">
<input v-model.trim="message" placeholder="请输入内容">
<p>{{message}}</p>
</div>
<script src="https://unpkg.com/vue@3/dist/vue.global.js"></script>
<script type="text/javascript">
const vm = Vue.createApp({
data() {
return {
message: ''
}
}
}).mount('#app');
</script>
