本文中的DOM事件模型为DOM level 2模型(W3C标准模型),现代浏览器均支持此模型。
事件捕获与冒泡
该事件模型中,一次事件共有三个过程:
- 捕获阶段(Capture Phase):事件从Window对象开始到目标元素的父元素(由外到内)。
- 目标阶段(Target Phase):事件到达目标元素。
- 冒泡阶段(Bubbling Phase):事件从目标元素的父元素到Window对象(由内到外)。
此过程可以通过以下代码来体现
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>DOM</title>
<style media="screen">
#div {
width: 300px;
height: 100px;
background: blue;
color: #fff;
text-align: center;
line-height: 100px;
}
</style>
</head>
<body>
<div id="div">
点击目标元素触发事件
</div>
<script type="text/javascript">
let div = document.querySelector('#div')
//捕获阶段事件函数
const f1 = function (e) {
console.log('捕获Captrue ' + this.toString());
}
//冒泡阶段事件函数
const f2 = function (e) {
console.log('冒泡Bubbling ' + this.toString());
}
//捕获阶段监听函数
div.addEventListener('click', f1, true);//目标元素监听函数
window.addEventListener('click', f1, true); //window节点监听函数
document.addEventListener('click', f1, true); //document节点监听函数
document.documentElement.addEventListener('click', f1, true); //html节点监听函数
document.body.addEventListener('click', f1, true); //body节点监听函数
//冒泡阶段监听函数
div.addEventListener('click', f2); //目标元素监听函数
window.addEventListener('click', f2); //window节点监听函数
document.addEventListener('click', f2); //document节点监听函数
document.documentElement.addEventListener('click', f2); //html节点监听函数
document.body.addEventListener('click', f2); //body节点监听函数
</script>
</body>
</html>
从下图可较清晰的看到事件模型的处理过程:
trap: 当在目标阶段触发多个监听事件时,此时没有捕获与冒泡之分,而是根据监听器绑定的顺序来依次执行。
事件监听函数
addEventListener():用于为元素添加事件监听
element.addEventListener(eventType, function, useCapture);
参数:
- 第一个为监听的事件的类型,如
click、mousedown等 - 第二个为事件出发后调用的函数
- 第三个参数类型为布尔值,表示为该事件监听用于冒泡阶段还是捕获阶段,true表示捕获,false表示冒泡,默认值为false,即默认为冒泡阶段
Event对象
Event 对象代表事件的状态,比如事件在其中发生的元素、键盘按键的状态、鼠标的位置、鼠标按钮的状态。event对象作为触发事件时执行回调函数的传入参数。
一些属性与方法:
-
event.target
event.target 属性返回触发/产生/生成事件的元素。可理解为用户操作的元素。
-
event.currentTarget
event.currentTarget 属性是在事件所绑定的元素。可理解为监听器所在的元素。一般this为event.currentTarget,但不推荐用this来代替,使用属性可读性更佳。
-
event.stopPropagation()
此方法可阻止当前事件继续进行捕捉(capturing)及冒泡(bubbling)阶段的传递。
dom.addEventListenner('click',function(event){ event.stopPropagation(); //事件不再继续传递 }) -
event.preventDefault()
如果事件可以被取消,就取消事件(即取消事件的预设/默认行为)。但不会影响事件的传递,事件仍会继续传递。
a.addEventListenner('click',function(event){ event.preventDefault(); //阻止a标签的默认跳转事件 })
tip: event.target指向触发事件的元素。 event.currentTarget指向监听事件的元素。