当你在 JavaScript 中使用事件时,你会发现事件处理函数中通常会有一个参数,我们通常命名为
event
或e
,这就是事件对象。事件对象是一个包含了与发生的事件相关的信息和方法的对象。
- 当一个事件发生时,就会有和这个事件相关的很多信息:
- 比如事件的类型是什么,你点击的是哪一个元素,点击的位置是哪里等等相关的信息
- 那么这些信息会被封装到一个Event对象中,这个对象由浏览器创建,称之为event对象
- 该对象给我们提供了想要的一些属性,以及可以通过该对象进行某些操作
- 如何获取这个event对象呢?
- event对象会在传入的事件处理(event handler)函数回调时,被系统传入
- 我们可以在回调函数中拿到这个event对象
event常见的属性和方法
如果我们的函数有多个参数,那么
event
对象应当是最后一个参数。例如:element.addEventListener('click', function(arg1, arg2, event) { console.log(arg1); // 打印第一个参数 console.log(arg2); // 打印第二个参数 console.log(event.target); // 打印点击的元素 });
在这个例子中,
event
对象是作为函数的第三个参数传入的。但请注意,除非你有明确的理由使用多个参数,通常我们都会将event
作为事件处理函数的第一个(也是唯一的)参数。
属性:
- type:事件的类型,例如"click","mouseover"等。
- target:触发事件的最深层元素,也就是真正的目标元素。
- currentTarget:绑定事件处理函数的元素,也就是正在处理事件的元素。
- eventPhase:事件当前所处的阶段,1表示捕获阶段,2表示处于目标阶段,3表示冒泡阶段。
- offsetX/offsetY:事件相对于事件目标的内部坐标位置,即相对于触发元素内部的X和Y坐标。
- clientX/clientY:事件相对于浏览器窗口可视区(viewport)的X和Y坐标。
- pageX/pageY:事件相对于整个文档的X和Y坐标。
- screenX/screenY:事件相对于电脑屏幕左上角的X和Y坐标。
target和currentTarget的区别
target
和currentTarget
是 JavaScript 中事件对象的两个属性,它们在事件处理中表示不同的元素:
- target:
target
属性返回触发事件的元素,也就是事件最初发生的地方,这个元素被称为目标元素或源元素。例如,如果你在一个按钮元素上点击,那么按钮就是事件的target
。- currentTarget:
currentTarget
属性返回其事件监听器被触发的元素。换句话说,currentTarget
是绑定事件处理器的元素。例如,如果你在一个按钮元素(这个按钮元素在一个 div 元素内部)上点击,而事件监听器是绑定在这个 div 上的,那么按钮是target
,div 是currentTarget
。在事件冒泡或者事件捕获的过程中,
target
是固定不变的,始终是事件最初发生的地方,而currentTarget
是随着事件的传递而改变的。如果在事件处理函数中没有使用到event.currentTarget
,那么通常可以不必关注它。但是在处理一些复杂的事件逻辑,尤其是涉及到事件代理的时候,currentTarget
就非常有用了。
方法:
- preventDefault():阻止事件的默认行为。例如,阻止链接的默认点击行为,即阻止链接打开一个新页面。
- stopPropagation():阻止事件的进一步传播,包括冒泡和捕获。例如,在嵌套元素中阻止点击事件冒泡到父元素。
这个例子创建了一个父元素和一个子元素,并在父元素上添加了一个点击事件监听器。当你点击子元素或父元素时,监听器将打印出关于事件的各种信息。
注意,当你点击子元素时,虽然子元素上的监听器会阻止事件冒泡,但是父元素的监听器仍然会被触发。这是因为,当一个事件发生时,浏览器首先在捕获阶段将事件传递到最深层的目标元素,然后在冒泡阶段将事件传回去。虽然
stopPropagation
阻止了事件的冒泡,但是在捕获阶段,事件仍然会到达父元素。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Event Object Example</title>
<style>
.container {
width: 300px;
height: 300px;
background-color: #eee;
position: relative;
}
.box {
width: 100px;
height: 100px;
background-color: #f66;
position: absolute;
left: 50px;
top: 50px;
}
</style>
</head>
<body>
<div class="container" id="container">
<div class="box" id="box"></div>
</div>
<script>
const container = document.getElementById('container');
const box = document.getElementById('box');
container.addEventListener('click', function(event) {
// 打印事件类型
console.log('Event Type: ', event.type); // "click"
// 打印触发事件的元素和处理事件的元素
console.log('Target Element: ', event.target); // box or container,取决于点击的元素
console.log('Current Target Element: ', event.currentTarget); // container
// 打印事件所处阶段
console.log('Event Phase: ', event.eventPhase); // 2 or 3,取决于点击的元素
// 打印相对于事件目标的坐标和相对于视窗、文档和屏幕的坐标
console.log('OffsetX: ', event.offsetX, 'OffsetY: ', event.offsetY);
console.log('ClientX: ', event.clientX, 'ClientY: ', event.clientY);
console.log('PageX: ', event.pageX, 'PageY: ', event.pageY);
console.log('ScreenX: ', event.screenX, 'ScreenY: ', event.screenY);
});
// 阻止默认行为和事件传播
box.addEventListener('click', function(event) {
event.preventDefault(); // 在此例中没有明显效果,因为 div 的点击没有默认行为
event.stopPropagation(); // 阻止事件冒泡到父元素
});
</script>
</body>
</html>
事件处理中函数的this
- 在函数中,我们也可以通过this来获取当前的发生元素:
这是因为在浏览器内部,调用event handler是绑定到当前的target上的,后续JS高级笔记中有详细讲解this的笔记