DOM事件流描述的是从页面中接收事件的顺序;事件发生时会在元素节点之间按照特定的顺序传播,这个传播过程即 DOM 事件流!
一.DOM事件流
比如我们给一个div注册了一个点击事件:
DOM事件流分为3个阶段:
- 捕获阶段
- 当前目标阶段
- 冒泡阶段
事件冒泡: IE 最早提出,事件开始时由最具体的元素接收,然后逐级向上传播到到 DOM 最顶层节点的过程。
事件捕获: 网景最早提出,由 DOM 最顶层节点开始,然后逐级向下传播到到最具体的元素接收的过程。
需要注意:
- JS 代码中只能执行捕获或者冒泡其中的一个阶段。
- onclick 和 attachEvent 只能得到冒泡阶段。
- addEventListener(type, listener[, useCapture])第三个参数如果是 true,表示在事件捕获阶段调用事件处理程序;如果是 false(不写默认就是false),表示在事件冒泡阶段调用事件处理程序。
- 实际开发中我们很少使用事件捕获,我们更关注事件冒泡。
- 有些事件是没有冒泡的,比如 onblur、onfocus、onmouseenter、onmouseleave
- 事件冒泡有时候会带来麻烦,有时候又会帮助很巧妙的做某些事件,所以它有利也有弊。
<body>
<div class="father">
<div class="son">son盒子</div>
</div>
<script>
// 冒泡阶段:如果addEventListener第三个参数是 false 或者省略那么则处于冒泡阶段 son -> father ->body -> html -> document
var son = document.querySelector('.son');
son.addEventListener('click', function() {
alert('son');
}, false);
var father = document.querySelector('.father');
father.addEventListener('click', function() {
alert('father');
}, false);
document.addEventListener('click', function() {
alert('document');
})
</script>
</body>
代码执行结果:
二.阻止事件冒泡
-
标准写法:利用事件对象里面的 stopPropagation()方法
e.stopPropagation() -
非标准写法:IE 6-8 利用事件对象 cancelBubble 属性
e.cancelBubble = true
三.事件委托
- 事件委托:称为事件代理, 在 jQuery 里面称为事件委派。
- 事件委托的原理:不是每个子节点单独设置事件监听器,而是事件监听器设置在其父节点上,然后利用冒泡原理影响设置每个子节点。
- 事件委托作用:我们只操作了一次 DOM ,提高了程序的性能。
<body>
<ul>
<li>
<div>事件委托</div>
</li>
</ul>
<script>
var ul = document.querySelector('ul');
ul.addEventListener('click', function(e) {
// e.target 这个可以得到我们点击的对象
e.target.style.backgroundColor = 'purple';
})
</script>
</body>