事件冒泡
事件流是网页元素接受事件的顺序,”DOM2 级事件“规定的事件流包括三个阶段:事件捕获阶段、处于目标阶段、事件冒泡阶段。首先发生的事件捕获,为捕获事件提供机会;然后是实际的目标接受事件;最后一个阶段是事件冒泡阶段,可以在这个阶段对事件做出相应。虽然捕获阶段在规定中规定不允许响应事件,但是实际上还是会执行,所以又两次机会获取到目标对象。
javascript
btn.addEventListener(eventType, function () {}, false);
// 第一个参数为事件名
// 第二个为事件处理程序
// 第三个为布尔值,true为事件捕获阶段调用事件处理程序,false为事件冒泡阶段调用事件处理程序,默认为false
来个例子:
html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<title>事件冒泡</title>
</head>
<body>
<div>
<button id="btn">按钮</button>
</div>
</body>
</html>
<script type="text/javascript">
var btn = document.getElementById('btn');
btn.addEventListener(
'click',
function () {
alert('事件捕获');
},
true,
);
btn.addEventListener(
'click',
function () {
alert('事件冒泡');
},
false,
);
</script>
依次弹出”事件捕获“和”事件冒泡“
如果反过来写
javascript
var btn = document.getElementById('btn');
btn.addEventListener(
'click',
function () {
alert('事件冒泡');
},
false,
);
btn.addEventListener(
'click',
function () {
alert('事件捕获');
},
true,
);
依次弹出则是:”事件冒泡“和”事件捕获“。
所以我们可以总结出:如果一个事件中同时有”冒泡“和”捕获“,那么就按照代码的书写顺序来执行
html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<title>事件冒泡</title>
</head>
<body>
<div>
<p id="parEle">
我是父元素
<span id="sonEle">我是子元素</span>
</p>
</div>
</body>
</html>
<script type="text/javascript">
var sonEle = document.getElementById('sonEle');
var parEle = document.getElementById('parEle');
parEle.addEventListener(
'click',
function () {
alert('父级 冒泡');
},
false,
);
parEle.addEventListener(
'click',
function () {
alert('父级 捕获');
},
true,
);
sonEle.addEventListener(
'click',
function () {
alert('子级冒泡');
},
false,
);
sonEle.addEventListener(
'click',
function () {
alert('子级捕获');
},
true,
);
</script>
当容器元素及嵌套元素,既在捕获阶段
又在冒泡阶段
调用事件处理程序时:事件按 DOM 事件流的顺序执行事件处理顺序:
- 父级捕获
- 子级冒泡
- 子级捕获
- 父级冒泡
且当事件处于目标阶段时,事件调用顺序决定于绑定事件的书写顺序,按照上面例子,先调用冒泡阶段的事件,再调用捕获阶段的事件。一次 alert 出”子级冒泡“,”子级捕获“