JavaScript 和 HTML 交互是通过事件实现, 而事件处理程序订阅事件从而执行相应的操作.
事件流
事件流描述的是 从页面接收事件的顺序.
事件冒泡: 从最具体的元素到最不具体的元素(从内到外); — IE
事件捕获: 从最不具体的元素到最具体的元素(从外到内); — Netscape
DOM 事件流: 先捕获后冒泡的方式.
DOM事件流包括三个阶段:
- 捕获阶段 (IE 低版本不支持该阶段)
- 目标阶段 (触发事件)
- 冒泡阶段 (回传文档)
事件处理程序
事件是用户或浏览器自身执行的动作, 事件处理程序(事件监听器)是响应事件的动作. 比如 click 事件的事件处理程序就是 onclick, 为事件指定处理程序的方式也有几种.
HTML 事件处理程序
在标签上绑定事件处理程序, HTML 和 js 紧密耦合1
<button onclick='alert('clicked')'>click me</button>
DOM 0级事件处理程序
将一个函数赋值给一个事件处理程序属性1
2
3
4var btn = document.querySelector('#btn');
btn.onclick = function () {
alert('clicked')
}
DOM 2级事件处理程序
定义了两个方法, 用于绑定事件处理程序和删除事件处理程序: addEventListener()
和removeEventListener()
. 所有的 DOM 节点都包含这两个方法, 方法有三个参数: 需要处理的事件名/ 处理函数/ 布尔值(true 为在捕获阶段调用; false 为在冒泡阶段调用)1
2
3
4
5
6
7
8
9var btn = document.querySelector('#btn');
// 绑定处理程序
btn.addEventListener('click', function () {
alert('clicked')
}, false);
// 移除处理程序(移除处理程序时, 第二个参数必须和绑定时一样)
btn.removeEventListener('click', function () {
alert('remove')
}, false)
IE 和 DOM2级事件处理程序的区别
- IE 事件处理程序
1
2
3
4
5
6
7
8
9
10var btn = docuemnt.querySelector('#btn');
// 绑定事件
btn.attachEvent('onclick', function () {
// this === window
alert('click on IE')
})
// 移除事件
btn.detachEvent('onclick', function () {
alert('remove on IE')
})
以上两种事件处理程序都支持绑定多个事件, DOM2级按照顺序
- 跨浏览器事件处理
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26const EventUtil = {
// 绑定事件处理程序
addHanlder: function (element, type, handler) {
if (element.addEventListener) {
element.addEventListener(type, handler, false)
}
else if (element.attachEvent) {
element.attachEvent('on' + type, handler)
}
else {
element['on' + type] = handler;
}
},
// 移除事件处理程序
removeHandler: function (element, type, handler) {
if (element.removeEventListener) {
element.removeEventListener(type, handler, false)
}
else if (element.detachEvent) {
element.detachEvent('on' + type, handler)
}
else {
element['on' + type] = null;
}
}
}
事件代理/ 委托
由于事件处理程序越多, 性能越差, 所以有了事件处理程序. 事件代理的原理是基于事件的冒泡机制实现的, 由上级节点代理完成事件绑定, 优点是:
节省内存占用, 减少事件注册. 比如在
ul
代理所有li
的点击事件
动态新增子级时, 无需再次绑定事件.
可能会提到currentTarget
和target
的区别: currentTarget 是注册事件时的目标(在事件处理程序中this
始终指向 currentTarget), target 是真正触发事件的目标.
1 | document.body.onclick = function (event) { |
事件对象
事件内置的 event 对象, 下面列举常用的几个事件对象属性:
- event || window.event
- event.preventDefault() || window.event.cancelBubble(Boolean)
阻止浏览器默认事件 - event.stopPropagation() || window.event.returnValue(Boolean)
阻止冒泡事件 - event.target || winow.event.srcElement
Created on 2017-12-10 by Cara