Skip to content

Commit aa393d9

Browse files
committed
docs(events): add 表单事件
1 parent 457474e commit aa393d9

File tree

6 files changed

+362
-240
lines changed

6 files changed

+362
-240
lines changed

chapters.yml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -59,8 +59,9 @@
5959
- events/model.md: 事件模型
6060
- events/event.md: Event 对象
6161
- events/mouse.md: 鼠标事件
62-
- events/keyboardevent.md: KeyboardEvent 接口,InputEvent 接口,CustomEvent 接口
62+
- events/keyboard.md: 键盘事件
6363
- events/progress.md: 进度事件
64+
- events/form.md: 表单事件
6465
- events/touch.md: 触摸事件
6566
- events/drag.md: 拖拉事件
6667
- events/globaleventhandlers.md: GlobalEventHandlers 接口

docs/events/event-type.md

Lines changed: 0 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -2,32 +2,10 @@
22

33
浏览器支持大量的事件,本章介绍其中一些主要的事件。
44

5-
## 键盘事件
6-
7-
键盘事件由用户击打键盘触发,主要有`keydown``keypress``keyup`三个事件,它们都继承了`KeyboardEvent`接口。
8-
9-
- `keydown`:按下键盘时触发。
10-
- `keypress`:按下有值的键时触发,即按下 Ctrl、Alt、Shift、Meta 这样无值的键,这个事件不会触发。对于有值的键,按下时先触发`keydown`事件,再触发这个事件。
11-
- `keyup`:松开键盘时触发该事件。
12-
13-
如果用户一直按键不松开,就会连续触发键盘事件,触发的顺序如下。
14-
15-
1. keydown
16-
1. keypress
17-
1. keydown
18-
1. keypress
19-
1. ...(重复以上过程)
20-
1. keyup
21-
225
## 焦点事件
236

247
- focus
258
- blur
269
- focusin
2710
- focusout
2811

29-
## 表单事件
30-
31-
- input
32-
- select
33-

docs/events/form.md

Lines changed: 199 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,199 @@
1+
# 表单事件
2+
3+
## 表单事件的种类
4+
5+
### input 事件
6+
7+
`input`事件当`<input>``<select>``<textarea>`的值发生变化时触发。对于复选框(`<input type=checkbox>`)或单选框(`<input type=radio>`),用户改变选项时,也会触发这个事件。另外,对于打开`contenteditable`属性的元素,只要值发生变化,也会触发`input`事件。
8+
9+
`input`事件的一个特点,就是会连续触发,比如用户每按下一次按键,就会触发一次`input`事件。
10+
11+
`input`事件对象继承了`InputEvent`接口。
12+
13+
该事件跟`change`事件很像,不同之处在于`input`事件在元素的值发生变化后立即发生,而`change`在元素失去焦点时发生,而内容此时可能已经变化多次。也就是说,如果有连续变化,`input`事件会触发多次,而`change`事件只在失去焦点时触发一次。
14+
15+
下面是`<select>`元素的例子。
16+
17+
```javascript
18+
/* HTML 代码如下
19+
<select id="mySelect">
20+
<option value="1">1</option>
21+
<option value="2">2</option>
22+
<option value="3">3</option>
23+
</select>
24+
*/
25+
26+
function inputHandler(e) {
27+
console.log(e.target.value)
28+
}
29+
30+
var mySelect = document.querySelector('#mySelect');
31+
mySelect.addEventListener('input', inputHandler);
32+
```
33+
34+
上面代码中,改变下拉框选项时,会触发`input`事件,从而执行回调函数`inputHandler`
35+
36+
### select 事件
37+
38+
`select`事件当在`<input>``<textarea>`里面选中文本时触发。
39+
40+
```javascript
41+
// HTML 代码如下
42+
// <input id="test" type="text" value="Select me!" />
43+
44+
var elem = document.getElementById('test');
45+
elem.addEventListener('select', function (e) {
46+
console.log(e.type); // "select"
47+
}, false);
48+
```
49+
50+
选中的文本可以通过`event.target`元素的`selectionDirection``selectionEnd``selectionStart``value`属性拿到。
51+
52+
### Change 事件
53+
54+
`Change`事件当`<input>``<select>``<textarea>`的值发生变化时触发。它与`input`事件的最大不同,就是不会连续触发,只有当全部修改完成时才会触发,另一方面`input`事件必然伴随`change`事件。具体来说,分成以下几种情况。
55+
56+
- 激活单选框(radio)或复选框(checkbox)时触发。
57+
- 用户提交时触发。比如,从下列列表(select)完成选择,在日期或文件输入框完成选择。
58+
- 当文本框或`<textarea>`元素的值发生改变,并且丧失焦点时触发。
59+
60+
下面是一个例子。
61+
62+
```javascript
63+
// HTML 代码如下
64+
// <select size="1" onchange="changeEventHandler(event);">
65+
// <option>chocolate</option>
66+
// <option>strawberry</option>
67+
// <option>vanilla</option>
68+
// </select>
69+
70+
function changeEventHandler(event) {
71+
console.log(event.target.value);
72+
}
73+
```
74+
75+
如果比较一下上面`input`事件的例子,你会发现对于`<select>`元素来说,`input``change`事件基本是等价的。
76+
77+
### invalid 事件
78+
79+
用户提交表单时,如果表单元素的值不满足校验条件,就会触发`invalid`事件。
80+
81+
```html
82+
<form>
83+
<input type="text" required oninvalid="console.log('invalid input')" />
84+
<button type="submit">提交</button>
85+
</form>
86+
```
87+
88+
上面代码中,输入框是必填的。如果不填,用户点击按钮提交时,就会触发输入框的`invalid`事件,导致提交被取消。
89+
90+
### reset 事件,submit 事件
91+
92+
这两个事件发生在表单对象`<form>`上,而不是发生在表单的成员上。
93+
94+
`reset`事件当表单重置(所有表单成员变回默认值)时触发。
95+
96+
`submit`事件当表单数据向服务器提交时触发。注意,`submit`事件的发生对象是`<form>`元素,而不是`<button>`元素,因为提交的是表单,而不是按钮。
97+
98+
## InputEvent 接口
99+
100+
`InputEvent`接口主要用来描述`input`事件的实例。该接口继承了`Event`接口,还定义了一些自己的实例属性和实例方法。
101+
102+
浏览器原生提供`InputEvent()`构造函数,用来生成实例对象。
103+
104+
```javascript
105+
new InputEvent(type, options)
106+
```
107+
108+
`InputEvent`构造函数可以接受两个参数。第一个参数是字符串,表示事件名称,该参数是必需的。第二个参数是一个配置对象,用来设置事件实例的属性,该参数是可选的。配置对象的字段除了`Event`构造函数的配置属性,还可以设置下面的字段,这些字段都是可选的。
109+
110+
- `inputType`:字符串,表示发生变更的类型(详见下文)。
111+
- `data`:字符串,表示插入的字符串。如果没有插入的字符串(比如删除操作),则返回`null`或空字符串。
112+
- `dataTransfer`:返回一个 DataTransfer 对象实例,该属性通常只在输入框接受富文本输入时有效。
113+
114+
`InputEvent`的实例属性主要就是上面三个属性,这三个实例属性都是只读的。
115+
116+
**(1)InputEvent.data**
117+
118+
`InputEvent.data`属性返回一个字符串,表示变动的内容。
119+
120+
```javascript
121+
// HTML 代码如下
122+
// <input type="text" id="myInput">
123+
var input = document.getElementById('myInput');
124+
input.addEventListener('input', myFunction, false);
125+
126+
function myFunction(e) {
127+
console.log(e.data);
128+
}
129+
```
130+
131+
上面代码中,如果手动在输入框里面输入`abc`,控制台会先输出`a`,再在下一行输出`b`,再在下一行输出`c`。然后选中`abc`,一次性将它们删除,控制台会输出`null`或一个空字符串。
132+
133+
**(2)InputEvent.inputType**
134+
135+
`InputEvent.inputType`属性返回一个字符串,表示字符串发生变更的类型。
136+
137+
对于常见情况,Chrome 浏览器的返回值如下。完整列表可以参考[文档](https://w3c.github.io/input-events/index.html#dom-inputevent-inputtype)
138+
139+
- 手动插入文本:`insertText`
140+
- 粘贴插入文本:`insertFromPaste`
141+
- 向后删除:`deleteContentBackward`
142+
- 向前删除:`deleteContentBackward`
143+
144+
**(3)InputEvent.dataTransfer**
145+
146+
`InputEvent.dataTransfer`属性返回一个 DataTransfer 实例。该属性只在文本框接受粘贴内容(insertFromPaste)或拖拽内容(`insertFromDrop`)时才有效。
147+
148+
## CustomEvent 接口
149+
150+
CustomEvent 接口用于生成自定义的事件实例。那些浏览器预定义的事件,虽然可以手动生成,但是往往不能在事件上绑定数据。如果需要在触发事件的同时,传入指定的数据,就可以使用 CustomEvent 接口生成的自定义事件对象。
151+
152+
浏览器原生提供`CustomEvent()`构造函数,用来生成 CustomEvent 事件实例。
153+
154+
```javascript
155+
new CustomEvent(type, options)
156+
```
157+
158+
`CustomEvent()`构造函数接受两个参数。第一个参数是字符串,表示事件的名字,这是必须的。第二个参数是事件的配置对象,这个参数是可选的。`CustomEvent`的配置对象除了接受 Event 事件的配置属性,只有一个自己的属性。
159+
160+
- `detail`:表示事件的附带数据,默认为`null`
161+
162+
下面是一个例子。
163+
164+
```javascript
165+
var event = new CustomEvent('build', { 'detail': 'hello' });
166+
167+
function eventHandler(e) {
168+
console.log(e.detail);
169+
}
170+
171+
document.body.addEventListener('build', function (e) {
172+
console.log(e.detail);
173+
});
174+
175+
document.body.dispatchEvent(event);
176+
```
177+
178+
上面代码中,我们手动定义了`build`事件。该事件触发后,会被监听到,从而输出该事件实例的`detail`属性(即字符串`hello`)。
179+
180+
下面是另一个例子。
181+
182+
```javascript
183+
var myEvent = new CustomEvent('myevent', {
184+
detail: {
185+
foo: 'bar'
186+
},
187+
bubbles: true,
188+
cancelable: false
189+
});
190+
191+
el.addEventListener('myevent', function (event) {
192+
console.log('Hello ' + event.detail.foo);
193+
});
194+
195+
el.dispatchEvent(myEvent);
196+
```
197+
198+
上面代码也说明,CustomEvent 的事件实例,除了具有 Event 接口的实例属性,还具有`detail`属性。
199+

docs/events/globaleventhandlers.md

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -217,3 +217,36 @@ el.ontouchstart = startTouch;
217217
用户点击`<dialog>`的取消按钮或按下`esc`键时,会触发`cancel`事件,导致执行`oncancel`属性。用户关闭`<dialog>`窗口,会触发`onclose`事件,导致执行`onclose`属性。
218218

219219
这两个属性在 DOM 中只对`<dialog>`元素有意义。
220+
221+
## 拖拉事件的属性
222+
223+
- ondrag:`drag`事件的监听函数
224+
- ondragend:`dragend`事件的监听函数
225+
- ondragenter:`dragenter`事件的监听函数
226+
- ondragexit:`dragexit`事件的监听函数
227+
- ondragleave:`dragleave`事件的监听函数
228+
- ondragover:`dragover`事件的监听函数
229+
- ondragstart:`dragstart`事件的监听函数
230+
- ondrop:`drop`事件的监听函数
231+
232+
下面是一个例子。
233+
234+
```html
235+
<div>
236+
<p
237+
id="source"
238+
ondrag="drag_handler(event);"
239+
ondragstart="dragstart_handler(event);"
240+
draggable="true"
241+
>
242+
拖动该元素
243+
</p>
244+
</div>
245+
<div
246+
id="target"
247+
ondrop="drop_handler(event);"
248+
ondragover="dragover_handler(event);"
249+
>
250+
目标区域
251+
</div>
252+
```

0 commit comments

Comments
 (0)