# 表单处理
在日常的开发中,表单随处都被使用到,如:登录,问题反馈功能等。对表单的数据收集和绑定也是很常规的工作。在一般开发中处理表单,需要通过操作 DOM 来实现,是一个相对繁琐且低效率的工作。然而在 Vue 项目中你可以用v-model
指令在表单 <input>
、<textarea>
及 <select>
元素上创建双向数据绑定。轻松地实现表单数据收集或绑定,提高了开发效率。它会根据控件类型自动选取正确的方法来更新元素。负责监听用户的输入事件以更新数据,并对一些极端场景进行一些特殊处理。接下来带领大家看看其基础用法。 # 基本用法
# 常用表单元素
元素 | |
---|---|
input[type=*] | 文本输入框 |
textarea | 多行文本 |
radio | 单选按钮 |
checkbox | 复选框 |
select | 选择框 |
# 注意
注意一:v-model
会忽略所有表单元素的 value
、checked
、selected
特性的初始值而总是将 Vue 实例的数据作为数据来源。直接给元素 value 赋值不会生效的,你应该通过 JavaScript 在组件的 data
选项中声明初始值。
注意二:v-model
在内部使用不同的属性为不同的输入元素并抛出不同的事件,具体体现我们在表单 修饰符小节,给大家说明:
text 和 textarea 元素使用
value
属性和input
事件(内部监听 input 事件);checkbox 和 radio 使用
checked
属性和change
事件(内部监听 change 事件);select 字段将
value
作为 prop 并将change
作为事件(内部监听 change 事件)。说明: change 和 input 区别就是,input 实时更新数据,change 不是实时更新。
input 监听
change 监听
带着注意事项,进入 Vue 表单处理学习。
# 文本
直接为文本绑定v-model
指令,在 data 数据项中声明绑定数据项,可以轻松完成双向数据绑定。让我们来看看神奇的v-model
指令。
例子:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta http-equiv="X-UA-Compatible" content="ie=edge" />
<title>syl-vue-test</title>
<!-- 引入 vue.js -->
<script src="https://labfile.oss.aliyuncs.com/courses/1262/vue.min.js"></script>
</head>
<body>
<div id="app">
<input v-model="msg" placeholder="请输入..." />
<p>输入的是: {{ msg }}</p>
</div>
<script>
var app = new Vue({
el: "#app",
data: {
msg: "",
},
});
</script>
</body>
</html>
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
运行结果:
# 多行文本
多行文本和文本用法相同,使用v-model
指令,在实例 data 中声明绑定的 message 数据项,即可完成多行文本数据双向绑定
例子:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta http-equiv="X-UA-Compatible" content="ie=edge" />
<title>vue</title>
<script src="https://labfile.oss.aliyuncs.com/courses/1262/vue.min.js"></script>
</head>
<body>
<div id="app">
<span>Multiline message is:</span>
<p style="white-space: pre-line;">{{ message }}</p>
<br />
<textarea v-model="message" placeholder="add multiple lines"></textarea>
</div>
<script>
var vue = new Vue({
el: "#app",
data() {
return {
message: "",
};
},
});
</script>
</body>
</html>
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
运行效果:
# 单选按钮
将单选按钮绑定到同一个 picked,即可完成数据绑定,当第一个单选被选中 picked 的值为第一个单选按钮的 value,同样当第二个单选被选中 picked 的值为第二个单选按钮的 value。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta http-equiv="X-UA-Compatible" content="ie=edge" />
<title>vue</title>
<script src="https://labfile.oss.aliyuncs.com/courses/1262/vue.min.js"></script>
</head>
<body>
<div id="app">
<!-- 将单选按钮绑定到同一个picked -->
<input type="radio" id="one" value="One" v-model="picked" />
<label for="one">One</label>
<br />
<input type="radio" id="two" value="Two" v-model="picked" />
<label for="two">Two</label>
<br />
<span>Picked: {{ picked }}</span>
</div>
<script>
var vue = new Vue({
el: "#app",
data() {
return {
picked: "",
};
},
});
</script>
</body>
</html>
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
运行效果:
# 复选框
复选框绑定的是一个布尔值(true or false),同样在复选框元素上使用v-model
指令,在实例 data 中声明 checked,即可完成复选框数据的双向绑定
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta http-equiv="X-UA-Compatible" content="ie=edge" />
<title>vue</title>
<script src="https://labfile.oss.aliyuncs.com/courses/1262/vue.min.js"></script>
</head>
<body>
<div id="app">
<input type="checkbox" id="checkbox" v-model="checked" />
<label for="checkbox">{{ checked }}</label>
</div>
<script>
//绑定布尔值
var vue = new Vue({
el: "#app",
data() {
return {
checked: false,
};
},
});
</script>
</body>
</html>
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
运行结果:
# 多个复选框
通常开发中,会用到多个复选框,那么我们就需要把复选框,绑定到同一个数组,方便数据收集。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta http-equiv="X-UA-Compatible" content="ie=edge" />
<title>vue</title>
<script src="https://labfile.oss.aliyuncs.com/courses/1262/vue.min.js"></script>
</head>
<body>
<div id="app">
<input type="checkbox" id="syl1" value="syl1" v-model="checkedNames" />
<label for="syl1">syl1</label>
<input type="checkbox" id="syl2" value="syl2" v-model="checkedNames" />
<label for="syl2">syl2</label>
<input type="checkbox" id="syl3" value="syl3" v-model="checkedNames" />
<label for="syl3">syl3</label>
<br />
<span>Checked names: {{ checkedNames }}</span>
</div>
<script>
var vue = new Vue({
el: "#app",
data() {
return {
checkedNames: [],
};
},
});
</script>
</body>
</html>
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
运行结果:
# 选择框
在 select 元素上使用v-model
指令,可以绑定当前选中的 option。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta http-equiv="X-UA-Compatible" content="ie=edge" />
<title>vue</title>
<script src="https://labfile.oss.aliyuncs.com/courses/1262/vue.min.js"></script>
</head>
<body>
<div id="app">
<!-- select标签是绑定 数据项 selected -->
<select v-model="selected">
<option disabled value="">请选择</option>
<option>A</option>
<option>B</option>
<option>C</option>
</select>
<span>Selected: {{ selected }}</span>
</div>
<script>
var vue = new Vue({
el: "#app",
data() {
return {
selected: "",
};
},
});
</script>
</body>
</html>
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
运行结果:
# 值绑定
# 文本和多行文本值绑定
直接在标签上指定 value 是不能成功的,会被 Vue 忽略
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta http-equiv="X-UA-Compatible" content="ie=edge" />
<title>syl-vue-test</title>
<!-- 引入 vue.js -->
<script src="https://labfile.oss.aliyuncs.com/courses/1262/vue.min.js"></script>
</head>
<body>
<div id="app">
<!-- 直接给value不会生效 -->
<input v-model="msg" value="hello" />
</div>
<script>
var app = new Vue({
el: "#app",
data: {
msg: "",
},
});
</script>
</body>
</html>
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
运行结果:
正确模式,通过 JavaScript 在组件的 data
选项中声明初始值:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta http-equiv="X-UA-Compatible" content="ie=edge" />
<title>syl-vue-test</title>
<!-- 引入 vue.js -->
<script src="https://labfile.oss.aliyuncs.com/courses/1262/vue.min.js"></script>
</head>
<body>
<div id="app">
<!-- 直接给value不会生效 -->
<input v-model="msg" />
<br />
<br />
<br />
<textarea v-model="msg"></textarea>
</div>
<script>
var app = new Vue({
el: "#app",
data: {
msg: "hello",
},
});
</script>
</body>
</html>
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
运行结果:
# 单选按钮
checkbox 和 radio 使用 checked
属性,所以直接给元素 value 值,当选中时 data 中声明的绑定项的值就为元素 value。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta http-equiv="X-UA-Compatible" content="ie=edge" />
<title>vue</title>
<script src="https://labfile.oss.aliyuncs.com/courses/1262/vue.min.js"></script>
</head>
<body>
<div id="app">
<!-- 当选中时,`picked` 为字符串 "a" -->
<input type="radio" v-model="picked" value="a" />
{{picked}}
</div>
<script>
var vue = new Vue({
el: "#app",
data() {
return {
picked: "",
};
},
});
</script>
</body>
</html>
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
运行结果:
# 复选框
复选框可以是布尔值,toggle 为 true 或 false,当选中时,toggle 为 true,未选中时,toggle 为 false
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta http-equiv="X-UA-Compatible" content="ie=edge" />
<title>vue</title>
<script src="https://labfile.oss.aliyuncs.com/courses/1262/vue.min.js"></script>
</head>
<body>
<div id="app">
<!-- 当复选框选中时,toggle的值为true,未选中为false -->
<input type="checkbox" v-model="toggle" />
{{toggle}}
</div>
<script>
var vue = new Vue({
el: "#app",
data() {
return {
toggle: false,
};
},
});
</script>
</body>
</html>
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
运行结果:
在日常开发中,复选框的值很多情况是特定的值,那么我们可以这样做,在标签中声明 true-value="yes" 和 false-value="no"这两个属性,当选中时就是 true-value 属性指定的值,当未选中时就是 false-value 属性值。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta http-equiv="X-UA-Compatible" content="ie=edge" />
<title>vue</title>
<script src="https://labfile.oss.aliyuncs.com/courses/1262/vue.min.js"></script>
</head>
<body>
<div id="app">
<input
type="checkbox"
v-model="toggle"
true-value="yes"
false-value="no"
/>
<p>toggle:{{toggle}}</p>
</div>
<script>
//通过true-value="yes" false-value="no"属性控制,选中时toggle值为yes,未选中时为no
var vue = new Vue({
el: "#app",
data() {
return {
toggle: "",
};
},
});
</script>
</body>
</html>
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
运行结果:
如果你只想要选中有值,你可以这样做,true-value 属性指定值,false-value 属性设为空值
<input type="checkbox" v-model="toggle" true-value="name" false-value="" />
# 选择框
选择框的值绑定,直接指定每个option
的value
,可以是固定的,也可以是使用 v-bind:value
动态绑定的:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta http-equiv="X-UA-Compatible" content="ie=edge" />
<title>vue</title>
<script src="https://labfile.oss.aliyuncs.com/courses/1262/vue.min.js"></script>
</head>
<body>
<div id="app">
<!-- 当选中第一个选项时,`selected` 为字符串 "abc" -->
<select v-model="selected">
<!-- 固定赋值value -->
<option value="abc">ABC</option>
<!-- 使用 v-bind 绑定值 -->
<option v-bind:value="optionValue">DEF</option>
</select>
<p>{{selected}}</p>
</div>
<script>
var vue = new Vue({
el: "#app",
data() {
return {
selected: "",
//第二个option 的值
optionValue: "efg",
};
},
});
</script>
</body>
</html>
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
运行效果:
# 修饰符
# .lazy
开始介绍表单处理时,我们说了几点注意,不同的元素,使用的值不同,抛出的事件也不同。可能开发中,我们不需要数据实时更新,那么,我们怎么将 input 事件与 change 事件替换,可以使用 .lazy 修饰符,可以将抛出事件由 input 改为 change ,使表单元素惰性更新,不实时更新。
例子:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta http-equiv="X-UA-Compatible" content="ie=edge" />
<title>vue</title>
<script src="https://labfile.oss.aliyuncs.com/courses/1262/vue.min.js"></script>
</head>
<body>
<div id="app">
<!--使用 .lazy 修饰符将文本框 抛出的事件改为 change 事件,不再实时更新,只有文本框失去焦点才更新数据 惰性更新 -->
<input v-model.lazy="msg" />
<p>{{msg}}</p>
</div>
<script>
var vue = new Vue({
el: "#app",
data: {
msg: "hello",
},
});
</script>
</body>
</html>
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
使用 .lazy
运行效果:
# .number
如果想自动将用户的输入值转为数值类型,可以给 v-model
添加 number
修饰符:
这通常很有用,因为即使在 type="number"
时,HTML 输入元素的值返回字符串(默认),需要自己进行类型转换。如果这个值无法被 parseFloat()
解析,则会返回原始的值。 给 v-model
添加 number
修饰符,用户即使输入的是非数值类型,也会进行转换,无法转换时,会返回原始的。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta http-equiv="X-UA-Compatible" content="ie=edge" />
<title>vue</title>
<script src="https://labfile.oss.aliyuncs.com/courses/1262/vue.min.js"></script>
</head>
<body>
<div id="app">
<p>没有使用 .number 修饰符</p>
<input v-model="number1" type="number" />
<!-- 使用typeof对值类型检测 -->
<p>{{typeof(number1)}}</p>
<p>使用 .number 修饰符</p>
<input v-model.number="number2" type="number" />
<!-- 使用typeof对值类型检测 -->
<p>{{typeof(number2)}}</p>
</div>
<script>
var vue = new Vue({
el: "#app",
data: {
number1: "",
number2: "",
},
});
</script>
</body>
</html>
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
运行结果:
# .trim
表单元素值首尾空格,自动过滤。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta http-equiv="X-UA-Compatible" content="ie=edge" />
<title>vue</title>
<script src="https://labfile.oss.aliyuncs.com/courses/1262/vue.min.js"></script>
</head>
<body>
<div id="app">
<input v-model.trim="msg" type="text" />
<p>首尾空格被过滤了:{{msg}}</p>
</div>
<script>
var vue = new Vue({
el: "#app",
data: {
msg: "",
},
});
</script>
</body>
</html>
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
运行结果:
# 综合小练习
表单数据收集与绑定
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta http-equiv="X-UA-Compatible" content="ie=edge" />
<title>vue</title>
<script src="https://labfile.oss.aliyuncs.com/courses/1262/vue.min.js"></script>
<style>
* {
padding: 0;
margin: 0;
}
html,
body {
width: 100%;
height: 100%;
overflow: hidden;
}
#app {
position: absolute;
top: 0;
left: 0;
bottom: 0;
right: 0;
margin: auto;
width: 400px;
height: 400px;
}
</style>
</head>
<body>
<div id="app">
<form class="app-form">
<span>name: </span>
<input type="text" v-model="username" />
<br />
<span>password:</span><input type="password" v-model="password" />
<br />
<span
>sex: </span
>
<input type="radio" id="man" value="man" v-model="sex" />
<label for="man">man</label>
<input type="radio" id="woman" value="woman" v-model="sex" />
<label for="woman">women</label>
<br />
<span>hobby:</span>
<input type="checkbox" id="game" value="game" v-model="hobby" />
<label for="game">game</label>
<input
type="checkbox"
id="basketball"
value="basketball"
v-model="hobby"
/>
<label for="basketball">basketball</label>
<input type="checkbox" id="study" value="study" v-model="hobby" />
<label for="study">study</label>
<br />
<br />
<p>名字:{{username}}</p>
<p>密码:{{password}}</p>
<p>性别:{{sex}}</p>
<p>爱好:{{hobby}}</p>
</form>
</div>
<script>
var vue = new Vue({
el: "#app",
data() {
return {
username: "",
password: "",
sex: "man", //性别单选默认勾选男
hobby: [],
};
},
});
</script>
</body>
</html>
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
运行效果: