Skip to content

Commit c07711e

Browse files
committed
docs(bom): add form
1 parent ed82d83 commit c07711e

File tree

3 files changed

+210
-3
lines changed

3 files changed

+210
-3
lines changed

chapters.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,7 @@
7979
- bom/location.md: Location 对象,URL 对象,URLSearchParams 对象
8080
- bom/arraybuffer.md: ArrayBuffer 对象,Blob 对象
8181
- bom/file.md: File 对象,FileList 对象,FileReader 对象
82+
- bom/form.md: 表单,FormData 对象
8283
- elements/: 附录:网页元素接口
8384
- elements/a.md: <a>
8485
- elements/image.md: <img>

docs/bom/form.md

Lines changed: 199 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
1-
# 表单
1+
# 表单,FormData 对象
22

3-
## 概述
3+
## 表单概述
44

55
表单(`<form>`)用来收集用户提交的数据,发送到服务器。比如,用户提交用户名和密码,让服务器验证,就要通过表单。表单提供多种控件,让开发者使用,具体的控件种类和用法请参考 HTML 语言的教程。本章主要介绍 JavaScript 与表单的交互。
66

@@ -44,6 +44,148 @@ user_name=张三&user_passwd=123&submit_button=提交
4444

4545
注意,实际提交的时候,只要键值不是 URL 的合法字符(比如汉字“张三”和“确定”),浏览器会自动对其进行编码。
4646

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+
47189
## 表单的内置验证
48190

49191
### 自动校验
@@ -197,7 +339,7 @@ if (document.getElementById('myInput').validity.rangeOverflow) {
197339
document.getElementById('prompt').innerHTML = txt;
198340
```
199341

200-
### 表单的 HTML 属性 novalidate
342+
### 表单的 novalidate 属性
201343

202344
表单元素的 HTML 属性`novalidate`,可以关闭浏览器的自动校验。
203345

@@ -206,6 +348,12 @@ document.getElementById('prompt').innerHTML = txt;
206348
</form>
207349
```
208350

351+
这个属性也可以在脚本里设置。
352+
353+
```javascript
354+
form.noValidate = true;
355+
```
356+
209357
如果表单元素没有设置`novalidate`属性,那么提交按钮(`<button>``<input>`元素)的`formnovalidate`属性也有同样的作用。
210358

211359
```html
@@ -351,4 +499,52 @@ The second line.
351499

352500
上面的 HTML 代码中,file 控件的`multiple`属性,指定可以一次选择多个文件;如果没有这个属性,则一次只能选择一个文件。
353501

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+
```
354550

docs/stdlib/regexp.md

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,16 @@ r.test(s) // false
104104

105105
上面代码指定从字符串的第五个位置开始搜索,这个位置是没有字符的,所以返回`false`
106106

107+
注意,带有`g`修饰符时,正则表达式内部会记住上一次的`lastIndex`属性,这时不应该更换所要匹配的字符串,否则会有一些难以察觉的错误。
108+
109+
```javascript
110+
var r = /bb/g;
111+
r.test('bb') // true
112+
r.test('-bb-') // false
113+
```
114+
115+
上面代码中,由于正则表达式`r`是从上一次的`lastIndex`位置开始匹配,导致第二次执行`test`方法时出现预期以外的结果。
116+
107117
`lastIndex`属性只对同一个正则表达式有效,所以下面这样写是错误的。
108118

109119
```javascript

0 commit comments

Comments
 (0)