事件冒泡:事件开始时由最具体的元素(文档中嵌套层次最深的那个节点)接收,然后逐级向上传播到较为不具体的节点(文档).即事件由最深的节点逐级向父级触发。
如例:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Event Bubbling Example</title>
</head>
<body>
<div id="myDiv">Click me</div>
</body>
</html>
如果你单击了页面中的<div>元素,那么这个click事件会按照如下顺序传播:
(1)<div>
(2)<body>
(3)<html>
(4)document
即click事件会如下图般传播:
具体实例:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Event Bubbling Example</title>
</head>
<body>
<div id="myDiv">
<button id="example">Click me</button>
</div>
</body>
<script>
var myDiv = document.getElementById('myDiv');
var example = document.getElementById('example');
myDiv.addEventListener('click',function(){
alert("我是myDiv");
});
example.addEventListener('click',function(){
alert("我是example");
});
</script>
</html>
在该实例中,点击按钮,首先弹出"我是example",接着自动弹出"我是myDiv";即发生事件冒泡,click事件逐级向上传播。
所有现代浏览器都支持事件冒泡。
如何阻止事件冒泡?
修改实例js代码如下:
var myDiv = document.getElementById('myDiv');
var example = document.getElementById('example');
myDiv.addEventListener('click',function(e){
alert("我是myDiv");
window.event? window.event.cancelBubble = true : e.stopPropagation();
});
example.addEventListener('click',function(e){
alert("我是example");
window.event? window.event.cancelBubble = true : e.stopPropagation();
});
在jQuery中直接使用e.stopPropagation阻止事件冒泡。
事件捕获:事件捕获与事件冒泡相反,它是不太具体的节点更早接收到事件,而最具体的节点最后接收的事件。即事件由document对象(或者window对象)到最深的节点逐级触发
如例:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Event Bubbling Example</title>
</head>
<body>
<div id="myDiv">Click me</div>
</body>
</html>
如果你单击了页面中的<div>元素,那么这个click事件会按照如下顺序传播:
(1)doucment
(2)<html>
(3)<body>
(4)<div>
即click事件会如下图般传播:
具体事例:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Event Bubbling Example</title>
</head>
<body>
<div id="myDiv">
<button id="example">Click me</button>
</div>
</body>
<script>
var myDiv = document.getElementById('myDiv');
var example = document.getElementById('example');
myDiv.addEventListener('click',function(){
alert("我是myDiv");
});
example.addEventListener('click',function(){
alert("我是example");
});
</script>
</html>
对于addEventListener()方法,第三个参数为布尔值,默认为false:事件冒泡;true:事件捕获。
在上述实例中,点击按钮,首先弹出"我是myDiv",接着自动弹出"我是example";即发生事件冒泡,click事件逐级向下传播
如何阻止事件捕获?
同理:
添加window.event? window.event.cancelBubble = true : e.stopPropagation();即可
事件委托:当事件处理程序过多时(即事件过多),我们一般会使用事件委托去处理。事件委托利用了事件冒泡的原理,只指定一个事件处理程序,就可以管理某一类型的所有事件。
实例如下:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Event Bubbling Example</title>
</head>
<body>
<div>
<ul id="box">
<li>我是li01</li>
<li>我是li02</li>
<li>我是li03</li>
<li>我是li04</li>
</ul>
</div>
</body>
<script>
var box = document.getElementById('box');
box.addEventListener('click',function(e){
var target = e.target || e.srcElement;
//target指向真正发生事件的DOM元素
alert(target.innerHTML);
});
</script>
</html>
实现效果:我们想要点击任何一个li时,弹出这个li标签的文本内容。
一般情况下,我们给每个li添加click事件。但是使用事件委托,我们给它们的父盒子ul#box添加click事件,并使用事件对象的属性e.target得到真正触发事件的DOM元素。
即因为事件冒泡的原理,点击li时,会冒泡到ul,触发我们给ul绑定的点击事件。如此,我们指定了一个事件就解决了多个事件的问题。