1
- # 表单
1
+ # 表单,FormData 对象
2
2
3
- ## 概述
3
+ ## 表单概述
4
4
5
5
表单(` <form> ` )用来收集用户提交的数据,发送到服务器。比如,用户提交用户名和密码,让服务器验证,就要通过表单。表单提供多种控件,让开发者使用,具体的控件种类和用法请参考 HTML 语言的教程。本章主要介绍 JavaScript 与表单的交互。
6
6
@@ -44,6 +44,148 @@ user_name=张三&user_passwd=123&submit_button=提交
44
44
45
45
注意,实际提交的时候,只要键值不是 URL 的合法字符(比如汉字“张三”和“确定”),浏览器会自动对其进行编码。
46
46
47
+ 点击` submit ` 控件,就可以提交表单。
48
+
49
+ ``` html
50
+ <form >
51
+ <input type =" submit" value =" 提交" >
52
+ </form >
53
+ ```
54
+
55
+ 上面表单就包含一个` submit ` 控件,点击这个控件,浏览器就会把表单数据向服务器提交。
56
+
57
+ 注意,表单里面的` <button> ` 元素如果没有用` type ` 属性指定类型,那么默认就是` submit ` 控件。
58
+
59
+ ``` html
60
+ <form >
61
+ <button >提交</button >
62
+ </form >
63
+ ```
64
+
65
+ 上面表单的` <button> ` 元素,点击以后也会提交表单。
66
+
67
+ 除了点击` submit ` 控件提交表单,还可以用表单元素的` submit() ` 方法,通过脚本提交表单。
68
+
69
+ ``` javascript
70
+ formElement .submit ();
71
+ ```
72
+
73
+ 表单元素的` reset() ` 方法可以重置所有控件的值(重置为默认值)。
74
+
75
+ ``` javascript
76
+ formElement .reset ()
77
+ ```
78
+
79
+ ## FormData 对象
80
+
81
+ ### 概述
82
+
83
+ 表单数据以键值对的形式向服务器发送,这个过程是浏览器自动完成的。但是有时候,我们希望通过脚本完成过程,构造和编辑表单键值对,然后通过` XMLHttpRequest.send() ` 方法发送。浏览器原生提供了 FormData 对象来完成这项工作。
84
+
85
+ FormData 首先是一个构造函数,用来生成实例。
86
+
87
+ ``` javascript
88
+ var formdata = new FormData (form);
89
+ ```
90
+
91
+ ` FormData() ` 构造函数的参数是一个表单元素,这个参数是可选的。如果省略参数,就表示一个空的表单,否则就会处理表单元素里面的键值对。
92
+
93
+ 下面是一个表单。
94
+
95
+ ``` html
96
+ <form id =" myForm" name =" myForm" >
97
+ <div >
98
+ <label for =" username" >用户名:</label >
99
+ <input type =" text" id =" username" name =" username" >
100
+ </div >
101
+ <div >
102
+ <label for =" useracc" >账号:</label >
103
+ <input type =" text" id =" useracc" name =" useracc" >
104
+ </div >
105
+ <div >
106
+ <label for =" userfile" >上传文件:</label >
107
+ <input type =" file" id =" userfile" name =" userfile" >
108
+ </div >
109
+ <input type =" submit" value =" Submit!" >
110
+ </form >
111
+ ```
112
+
113
+ 我们用 FormData 对象处理上面这个表单。
114
+
115
+ ``` javascript
116
+ var myForm = document .getElementById (' myForm' );
117
+ var formData = new FormData (myForm);
118
+
119
+ // 获取某个控件的值
120
+ formData .get (' username' ) // ""
121
+
122
+ // 设置某个控件的值
123
+ formData .set (' username' , ' 张三' );
124
+
125
+ formData .get (' username' ) // "张三"
126
+ ```
127
+
128
+ ### 实例方法
129
+
130
+ FormData 提供以下实例方法。
131
+
132
+ - ` FormData.get(key) ` :获取指定键名对应的键值,参数为键名。如果有多个同名的键值对,则返回第一个键值对的键值。
133
+ - ` FormData.getAll(key) ` :返回一个数组,表示指定键名对应的所有键值。如果有多个同名的键值对,数组会包含所有的键值。
134
+ - ` FormData.set(key, value) ` :设置指定键名的键值,参数为键名。如果键名不存在,会添加这个键值对,否则会更新指定键名的键值。如果第二个参数是文件,还可以使用第三个参数,表示文件名。
135
+ - ` FormData.delete(key) ` :删除一个键值对,参数为键名。
136
+ - ` FormData.append(key, value) ` :添加一个键值对。如果键名重复,则会生成两个相同键名的键值对。如果第二个参数是文件,还可以使用第三个参数,表示文件名。
137
+ - ` FormData.has(key) ` :返回一个布尔值,表示是否具有该键名的键值对。
138
+ - ` FormData.keys() ` :返回一个遍历器对象,用于` for...of ` 循环遍历所有的键名。
139
+ - ` FormData.values() ` :返回一个遍历器对象,用于` for...of ` 循环遍历所有的键值。
140
+ - ` FormData.entries() ` :返回一个遍历器对象,用于` for...of ` 循环遍历所有的键值对。如果直接用` for...of ` 循环遍历 FormData 实例,默认就会调用这个方法。
141
+
142
+ 下面是` get() ` 、` getAll() ` 、` set() ` 、` append() ` 方法的例子。
143
+
144
+ ``` javascript
145
+ var formData = new FormData ();
146
+
147
+ formData .set (' username' , ' 张三' );
148
+ formData .append (' username' , ' 李四' );
149
+ formData .get (' username' ) // "张三"
150
+ formData .getAll (' username' ) // ["张三", "李四"]
151
+
152
+ formData .append (' userpic[]' , myFileInput .files [0 ], ' user1.jpg' );
153
+ formData .append (' userpic[]' , myFileInput .files [1 ], ' user2.jpg' );
154
+ ```
155
+
156
+ 下面是遍历器的例子。
157
+
158
+ ``` javascript
159
+ var formData = new FormData ();
160
+ formData .append (' key1' , ' value1' );
161
+ formData .append (' key2' , ' value2' );
162
+
163
+ for (var key of formData .keys ()) {
164
+ console .log (key);
165
+ }
166
+ // "key1"
167
+ // "key2"
168
+
169
+ for (var value of formData .values ()) {
170
+ console .log (value);
171
+ }
172
+ // "value1"
173
+ // "value2"
174
+
175
+ for (var pair of formData .entries ()) {
176
+ console .log (pair[0 ] + ' : ' + pair[1 ]);
177
+ }
178
+ // key1: value1
179
+ // key2: value2
180
+
181
+ // 等同于遍历 formData.entries()
182
+ for (var pair of formData) {
183
+ console .log (pair[0 ] + ' : ' + pair[1 ]);
184
+ }
185
+ // key1: value1
186
+ // key2: value2
187
+ ```
188
+
47
189
## 表单的内置验证
48
190
49
191
### 自动校验
@@ -197,7 +339,7 @@ if (document.getElementById('myInput').validity.rangeOverflow) {
197
339
document .getElementById (' prompt' ).innerHTML = txt;
198
340
```
199
341
200
- ### 表单的 HTML 属性 novalidate
342
+ ### 表单的 novalidate 属性
201
343
202
344
表单元素的 HTML 属性` novalidate ` ,可以关闭浏览器的自动校验。
203
345
@@ -206,6 +348,12 @@ document.getElementById('prompt').innerHTML = txt;
206
348
</form >
207
349
```
208
350
351
+ 这个属性也可以在脚本里设置。
352
+
353
+ ``` javascript
354
+ form .noValidate = true ;
355
+ ```
356
+
209
357
如果表单元素没有设置` novalidate ` 属性,那么提交按钮(` <button> ` 或` <input> ` 元素)的` formnovalidate ` 属性也有同样的作用。
210
358
211
359
``` html
@@ -351,4 +499,52 @@ The second line.
351
499
352
500
上面的 HTML 代码中,file 控件的` multiple ` 属性,指定可以一次选择多个文件;如果没有这个属性,则一次只能选择一个文件。
353
501
502
+ ``` javascript
503
+ var fileSelect = document .getElementById (' file' );
504
+ var files = fileSelect .files ;
505
+ ```
506
+
507
+ 然后,新建一个 FormData 实例对象,模拟发送到服务器的表单数据,把选中的文件添加到这个对象上面。
508
+
509
+ ``` javascript
510
+ var formData = new FormData ();
511
+
512
+ for (var i = 0 ; i < files .length ; i++ ) {
513
+ var file = files[i];
514
+
515
+ // 只上传图片文件
516
+ if (! file .type .match (' image.*' )) {
517
+ continue ;
518
+ }
519
+
520
+ formData .append (' photos[]' , file, file .name );
521
+ }
522
+ ```
523
+
524
+ 最后,使用 Ajax 向服务器上传文件。
525
+
526
+ ``` javascript
527
+ var xhr = new XMLHttpRequest ();
528
+
529
+ xhr .open (' POST' , ' handler.php' , true );
530
+
531
+ xhr .onload = function () {
532
+ if (xhr .status !== 200 ) {
533
+ console .log (' An error occurred!' );
534
+ }
535
+ };
536
+
537
+ xhr .send (formData);
538
+ ```
539
+
540
+ 除了发送 FormData 实例,也可以直接 AJAX 发送文件。
541
+
542
+ ``` javascript
543
+ var file = document .getElementById (' test-input' ).files [0 ];
544
+ var xhr = new XMLHttpRequest ();
545
+
546
+ xhr .open (' POST' , ' myserver/uploads' );
547
+ xhr .setRequestHeader (' Content-Type' , file .type );
548
+ xhr .send (file);
549
+ ```
354
550
0 commit comments