这是对DOM事件的复杂性的广泛探索。首先,我们将深入研究各种类型的DOM事件,研究它们的每个独特特征及其触发方式。此外,我们将仔细研究一些更常见的DOM事件方面,例如事件的传播和冒泡。
什么是浏览器活动?
让我们简单地以这种方式说一个事件是一个对象,其中包含有关该特定事件的信息的属性,例如,触发了该事件的元素以及有关该特定事件的许多其他信息。
事件可以概括为2个类别
- 用户代理事件
- 合成事件
根据用户交互或任何其他浏览器(页面)任务完成浏览器的用户代理事件已完成。
例如
- 用户点击按钮
- 用户提交表格
- 所有资源已下载。
,并且可能会更多,我们可以在事件中添加听众以收听事件
window.addEventlistner('load',(event)=>{console.log(event));
合成事件
另一方面,合成事件是应用程序创建/发射的事件。
例如
const event = new Event('myEvent', {bubbles:true, cancelable: true});
//dispatch events
document.dispatchEvent(event);
//events can be dispatched from any element
document.getElementbyId('myDiv').dispatchEvent(event)
如果我们想传递数据,则可以使用CustomEvent()
。
const event = new CustomEvent('myCustomEvent', {detail: {message:'hello world'});
elem.addEventListner('myCustomEven', (event)=>{
console.log(event.detial.message)
})
isTrusted
是事件对象中的属性,用于用户代理派遣事件,而对启动的应用程序(开发人员)false。
事件阶段
当我们进一步检查事件对象时,我们还会获得属性名称eventPhase
。为了了解此属性,让我们首先了解什么是CAPTURING_PHASE
和BUBBLEING_PHASE
。
当事件派遣时,将在事件中发生在文档(root),然后返回目标元素(在上图按钮中)。从上到下的流量称为捕获相位,底部到顶部称为***** 起泡阶段。 *** **让我们向前迈出一步,并用代码理解上图
<!DOCTYPE html>
<html>
<head>
<title>Parcel Sandbox</title>
<meta charset="UTF-8" />
</head>
<body >
<form id='submit_form' style="border:1px solid red; padding: 4rem">
<button type='submit' id='submit_button'>Submit<button>
</div>
</form>
<script>
function eventListener(event) {
console.log({
target: event.target,
currentTarget: event.currentTarget,
phase: event.eventPhase,
type: event.type
});
}
const form = document.getElementById("submit_form");
const buttonContainer = document.getElementById("button-wrapper");
const submit = document.getElementById("submit_button");
form.addEventListener("click", eventListener);
buttonContainer.addEventListener("click", eventListener);
submit.addEventListener("click", eventListener);
</script>
</body>
</html>
这是一个漫长的例子,让我们将其分解。我们有一个简单的表格,后来我们将一些事件听众附加到它上。 addEventListner()
函数获取3个参数
- 事件侦听器应该听的事件名称
- 应该称呼的回调函数。
- 最后一个是选项或 usecapture。这是一个可选的参数。
所有参数都以我们关心的唯一论点为 option 和 usecapture。
该选项具有这些参数。
- 捕获:默认值为false。该事件将首先用附加事件侦听器的当前元素(即在DOM树中的元素)捕获,然后将其派发到任何事件目标
- 一次:应调用事件一次,默认情况下删除
- 被动:如果TUME告诉浏览器,即使在回调函数中存在
preventDefault
,回调函数也不会具有preventDefault().
。 - 信号:它用于通过提供
AbortSignal
来删除事件听众。我们将稍后在此博客中讨论中止信号。
捕获和冒泡阶段
在上面的示例中,我们在文档,正文,表单和按钮上附上了上述示例,输出将如下
{target: button#submit_button, currentTarget: button#submit_button, phase: 2, type: 'click'}
{target: button#submit_button, currentTarget: div#button-wrapper, phase: 3, type: 'click'}
{target: button#submit_button, currentTarget: form#submit_form, phase: 3, type: 'click'}
要理解这一点,我们首先需要研究Event
对象。用户代理生成的事件对象主要具有这些属性
-
type
:类型是单击,提交等事件的类型。您可以阅读有关它的更多信息。 -
eventTaget
:返回事件发生的元素或null。 -
currentTarget
:返回正在收听事件的元素 -
eventPhase
:这是有趣的。事件阶段通常返回这些值之一0,1,2,3。这些价值是什么?事件阶段有这些枚举
NONE = 0
CAPTURING_PHASE = 1;
AT_TARGET = 2;
BUBBELING_PHASE = 3;
让我们一一理解这些值中的每一个。在上面的示例上下文中,<button />
元素由div
包裹,该元素进一步嵌套在form
中。因此,单击按钮后,div
和from
处于捕获阶段。但是在控制台中,我们没有看到任何eventPhase
是1(即捕获)事件听众没有被调用。
要在捕获阶段中调用事件侦听器回调函数,我们需要在事件中指定true
。
document.body.addEventListener("click", eventListener, true);
// or
document.body.addEventListener("click", eventListener, { capture:true });
传播
现在我们对事件阶段有了深刻的了解。让我们进一步研究如何阻止处理程序被调用。我们有2种停止事件传播的方法。
-
event.stopPropagation()
和 event.stopImmediatePropagation()
假设我们在元素上附上了多个事件处理程序。我们有stopHandler()
和eventListenerLogs()
<!DOCTYPE html>
<html>
<head>
<title>Parcel Sandbox</title>
<meta charset="UTF-8" />
</head>
<body>
<form id='submit_form' style="border:1px solid red; padding: 4rem">
<div id='button-wrapper' style="border:1px solid black; padding: 4rem"">
<button type='button' id='submit_button'>Submit<button>
</div>
</form>
<script>
function stopHandler(event) {
event.stopPropagation();
console.log({
target: event.target,
element: event.currentTarget,
phase: event.eventPhase,
type: event.type
});
}
const form = document.getElementById("submit_form");
document.body.addEventListener("click", eventListener, false);
form.addEventListener("click", stopHandler, false);
form.addEventListener("click", eventListener, false);
</script>
</body>
</html>
我们已将事件处理程序附加到body
和form
元素。当我们单击按钮时,事件发生在BUBBLEING_PHASE
中,事件传播的顺序应为
但是,由于我们有event.stopPropagation()
,因此在形式级别上。控制台O/P是
{target: button#submit_button, element: form#submit_form, phase: 3, type: 'click'}
{target: button#submit_button, element: form#submit_form, phase: 3, type: 'click'}
我们必须将事件处理程序附加到form
元素上。
如果我们只想只听一次事件,那么我们可以使用event.stopImmediatePropagation()
function stopHandler(event) {
event.stopImmediatePropagation();
console.log({
target: event.target,
element: event.currentTarget,
phase: event.eventPhase,
type: event.type
});
}
现在输出为
{target: button#submit_button, element: form#submit_form, phase: 3, type: 'click'}
可取消
根据事件的初始化方式,可取消的事件仅阅读属性返回true
或false
。使用event.preventDefault()
可以取消大多数本机事件。称此功能就像事件从未发生过。我们可以创建一个syntheticEvent
并使其不可能。
const myCoustomEvent = new CoustomEvent("my-coustom",{
cancelable:true
})
document.addEventListener('my-event', function (event) {
event.preventDefault()
})
console.log(
document.dispatchEvent(event) ? 'Event was not cancelled' : 'Event was cancelled'
)
//output
//"Event was cancelled"
如果我们将cancelable
属性更改为false,则输出将为Event was not cancelled
。
预防默认
event.preventDefault()
将阻止本地元素动作发生。这意味着该事件的工作方式不会像事件从未发生过一样起作用。
结论。
总结了我们关于事件以及如何创建自定义事件的讨论。我们介绍了触发事件的各个阶段并探讨了可取消事件。
感谢您的阅读。如果我错过了任何东西,请在评论部分告诉我。