事件冒泡、事件捕捉和事件委托

如图是事件流的经过,
事件流

事件捕获

事件捕获是从外层元素到目标元素的过程,事件冒泡是从目标元素到外层元素的过程

1
2
3
<div id="wrapper">
<button id="event">事件处理程序</button>
</div>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
var wrapper = document.getElementById('wrapper');
var event = document.getElementById('event');
// 理解事件流
wrapper.addEventListener('click', function (e) {
console.log('捕获阶段执行父元素wrapper的事件处理程序');
}, true); // true - 事件句柄在捕获阶段执行
wrapper.addEventListener('click', function (e) {
console.log('冒泡阶段执行父元素wrapper的事件处理程序');
}, false); // false- 默认。事件句柄在冒泡阶段执行
event.addEventListener('click', function (e) {
console.log('捕获阶段执行子元素event的事件处理程序');
}, true);
event.addEventListener('click', function (e) {
console.log('冒泡阶段执行子元素event的事件处理程序');
}, false);
  • 输出结果
    捕获阶段执行父元素wrapper的事件处理程序
    捕获阶段执行子元素event的事件处理程序
    冒泡阶段执行父元素wrapper的事件处理程序
    冒泡阶段执行子元素event的事件处理程序

阻止冒泡

事件冒泡可以形象地比喻为把一颗石头投入水中,泡泡会一直从水底冒出水面。也就是说,事件会从最内层的元素开始发生,一直向上传播,直到document对象。

1
2
3
<div id="propagation">
<button id="proEvent">阻止冒泡处理程序</button>
</div>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
// 阻止冒泡
var propagation = document.getElementById('propagation');
var proEvent = document.getElementById('proEvent');
propagation.addEventListener('click', function (e) {
console.log('捕获阶段执行父元素propagation的事件处理程序');
}, true);
propagation.addEventListener('click', function (e) {
console.log('冒泡阶段执行父元素propagation的事件处理程序');
}, false);
proEvent.addEventListener('click', function (e) {
console.log('捕获阶段执行子元素proEvent的事件处理程序');
}, true);
proEvent.addEventListener('click', function (e) {
e.stopPropagation();
console.log('冒泡阶段执行子元素proEvent的事件处理程序');
}, false);
  • 输出结果
    捕获阶段执行父元素wrapper的事件处理程序
    捕获阶段执行子元素event的事件处理程序
    冒泡阶段执行父元素wrapper的事件处理程序

事件委托

事件委托就是把一个元素响应事件(click、keydown……)的函数委托到另一个元素

1
2
3
4
5
6
7
<ul>
<li>apple</li>
<li>banana</li>
<li>peal</li>
<li>cat</li>
<li>rabbit</li>
</ul>
1
2
3
4
5
6
7
8
9
10
11
12
13
// 事件委托
var li = document.getElementsByTagName('li');
for (var i = 0; i < li.length; i++) {
li[i].setAttribute('i', i + 1);
}
var ul = document.getElementsByTagName('ul')[0];
ul.addEventListener('click', function (e) {
var target = e.target;
if (e.target && e.target.nodeName.toUpperCase() == 'LI') {
var b = e.target.getAttribute('i');
console.log('这是第' + b + '个<li>元素');
}
})