本文不会讲述事件的基本知识,只记录一下一些疑惑点以做备忘。
冒泡和捕获
DOM的事件操作(监听和触发),都定义在EventTarget接口。
一个事件发生后,会在子元素和父元素上传播,传播分三个阶段:\
- 从window对象传导到目标节点,自上而下,为捕获
- 在目标节点上触发,为目标阶段
- 从目标对象传导回window,自下而上,为冒泡
el.addEventListener('click', func, true); // true 表示在捕获阶段触发
el.addEventListener('click', func, false); // false 表示在冒泡阶段触发
demo:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width,initial-scale=1,minimum-scale=1,maximum-scale=1,user-scalable=no" />
<title>dom</title>
</head>
<style>
div {
position: relative;
width: 100px;
height: 100px;
border: 1px solid green;
}
p {
position: absolute;
top: 20px;
left: 20px;
width: 50px;
height: 50px;
border: 1px solid red;
}
</style>
<body>
<div>
父
<p>子</p>
</div>
<script>
var div = document.querySelector('div');
var p = document.querySelector('p');
function callback(event) {
var tag = event.currentTarget.tagName;
console.log('Tag: ' + tag)
}
// 点击父: DIV 点击子: P DIV
div.addEventListener('click', callback, false);
p.addEventListener('click', callback, false);
// 父: DIV 子: DIV P
div.addEventListener('click', callback, true);
p.addEventListener('click', callback, true);
// 父: DIV 子: P DIV
div.addEventListener('click', callback, false);
p.addEventListener('click', callback, true);
// 父: DIV 子: DIV P
div.addEventListener('click', callback, true);
p.addEventListener('click', callback, false);
</script>
</body>
</html>
dispatchEvent
事件发生后,会产生一个事件对象,作为参数传给监听函数。浏览器原生提供了Event对象,所有的事件都是这个对象的实例。
event = new Event(type, options);// 参数一,事件名称; 参数二,事件对象的配置对象
options配置项:
- bubbles:布尔值,默认false,可选,表示事件对象是否冒泡
- cancelable:布尔值,默认false,可选,表示事件是否可以被取消
<body>
<div>
div
<p>p</p>
</div>
<script>
var div = document.querySelector('div');
var p = document.querySelector('p');
function callback(event) {
var tag = event.currentTarget.tagName;
console.log('Tag: ' + tag);
}
div.addEventListener('click', callback, false);
var click = new Event('click');
p.dispatchEvent(click);
</script>
</body>
点击只触发了div事件,p的dispatchEvent触发事件没有生效。
<body>
<div>
div
<p>p</p>
</div>
<script>
var div = document.querySelector('div');
var p = document.querySelector('p');
function callback(event) {
var tag = event.currentTarget.tagName;
console.log('Tag: ' + tag);
}
div.addEventListener('click', callback, false);
var click = new Event('click', {
bubbles: true
});
p.dispatchEvent(click);
</script>
</body>
进入页面,p.dispatchEvent就生效了,可以冒泡触发其父div的事件。
Event.currentTarget和Event.target
两个都是Event的实例属性。
事件发生后,会经历捕获和冒泡两个阶段,依次通过多个DOM节点,因此,任意时点都有两个与事件相关的节点。一个是原始触发节点(Event.target),一个是正在通过的节点(Event.currentTarget,随着事件传播会变),前者通常是后者的后代节点。
// HTML 代码为
// <p id="para">Hello <em>World</em></p>
function hide(e) {
// 不管点击 Hello 或 World,总是返回 true
console.log(this === e.currentTarget);
// 点击 Hello,返回 true
// 点击 World,返回 false
console.log(this === e.target);
}
document.getElementById('para').addEventListener('click', hide, false);
e.target总是指向原始点击位置的那个节点,而e.currentTarget指向事件传播过程中正在经过的那个节点,由于监听函数只有在事件经过时才会触发,所以e.currentTarget总是等于监听函数内部的this。
Event属性还有
- Event.bubbles
- Event.eventPhase
- Event.cancelable
- Event.cancelBubble
- event.defaultPrevented
- Event.type
- Event.timeStamp 等
比较全的事件类型说明:
developer.aliyun.com/article/875… blog.liuyunzhuge.com/2020/05/16/…