JavaScript 事件冒泡和事件委托

JavaScript(事件流、事件委托、实例化、dom节点) 阅读详情
AI摘要

本文围绕JavaScript的事件冒泡和事件委托展开。介绍了事件冒泡的传播机制、基本用法、捕获阶段及应用场景,分析了其优缺点;阐述了事件委托的概念、核心机制、用法和适用场景,也指出了优缺点;最后说明事件委托依赖事件冒泡机制,利用其特点实现子元素事件集中处理。

一、事件冒泡

1.1 什么是事件冒泡?

事件冒泡 是一种 DOM 事件传播机制。当一个事件发生在某个元素上时,它会按照从最具体的目标元素到其祖先元素的顺序依次触发,直到到达 document 或 window(顶层元素)。这一机制使得子元素触发的事件可以“冒泡”到父元素上。

1.2 事件传播机制

事 当 DOM 中的某个事件(如点击)发生时,会按照以下三个阶段传播:

  1. 捕获阶段(Capture Phase):
    • 事件从顶层元素(window 或 document)向目标元素传播。
    • 此阶段主要用于捕获事件。
    • 默认情况下,捕获阶段不会触发事件处理程序。
  1. 目标阶段(Target Phase):
    • 事件到达目标元素,并触发绑定在目标元素上的事件处理程序。
  1. 冒泡阶段(Bubble Phase):
    • 事件从目标元素向上传播,依次经过其父元素、祖先元素,最终到达 document 或 window。

1.3 事件冒泡的基本用法

1.3.1 如何使用事件冒泡

假设有如下的 HTML 结构:

<div id="grandparent">
  <div id="parent">
    <button id="child">Click me</button>
  </div>
</div>

传统 JavaScript 示例

document.getElementById('grandparent').addEventListener('click', () => {
    console.log('Grandparent clicked');
});

document.getElementById('parent').addEventListener('click', () => {
    console.log('Parent clicked');
});

document.getElementById('child').addEventListener('click', () => {
    console.log('Child clicked');
});

当点击 button 时,输出:

Child clicked
Parent clicked
Grandparent clicked
  1. 事件先触发目标元素 button 的事件处理程序。
  2. 然后事件冒泡到其父元素 div#parent,触发其事件处理程序。
  3. 最后事件冒泡到祖先元素 div#grandparent,触发其事件处理程序。

上面事件传播的顺序是:目标阶段 → 冒泡阶段。

1.3.2 如何阻止事件冒泡

调用 event.stopPropagation() 可以阻止事件从目标元素冒泡到父元素。

document.getElementById('child').addEventListener('click', (event) => {
  event.stopPropagation(); // 阻止冒泡
  console.log('Child clicked');
});

document.getElementById('parent').addEventListener('click', () => {
  console.log('Parent clicked');
});

点击 button 时,只输出:

Child clicked

父元素和祖先元素的事件处理程序不会被触发。

1.4 事件捕获

1.4.1 如何监听捕获阶段事件

默认情况下,事件处理程序只会在 目标阶段 和 冒泡阶段 触发。如果需要在捕获阶段监听事件,可以在绑定事件时将 addEventListener 的第三个参数设置为 true。

document.getElementById('grandparent').addEventListener(
    'click',
    () => {
        console.log('Grandparent clicked during capture');
    },
    true // 捕获阶段监听
);

当点击 button 时,上面输出顺序变为:

Grandparent clicked during capture
Child clicked
Parent clicked
Grandparent clicked

捕获阶段的事件处理程序先于目标阶段和冒泡阶段执行。

1.4.2 事件捕获与冒泡的区别

特性

捕获阶段

冒泡阶段

传播方向

从顶层到目标元素

从目标元素到顶层

默认行为

默认不触发处理程序

默认触发绑定的事件处理程序

应用场景

捕获特殊情况(如全局监听)

事件委托、常见交互

1.5 应用场景

1.5.1 事件委托

事件委托 是事件冒泡最常见的应用场景,通过在父元素上绑定事件处理程序,可以监听所有子元素的事件,而不需要逐一为每个子元素绑定事件。

假设有一个动态列表,点击列表项时触发某些逻辑:

<ul id="list">
  <li>Item 1</li>
  <li>Item 2</li>
</ul>

动态添加一个列表项:

document.getElementById('list').addEventListener('click', (event) => {
    //通过event.target判断具体子元素,从而执行相应的逻辑
    if (event.target.tagName === 'LI') {
        console.log('Clicked item:', event.target.textContent);
    }
});

// 动态添加列表项
const newItem = document.createElement('li');
newItem.textContent = 'Item 3';
document.getElementById('list').appendChild(newItem);

1.5.2 表单事件处理

对于表单中的多个输入框,可以利用事件冒泡将验证逻辑集中在父元素上,而不是为每个输入框单独绑定事件。

<form id="form">
  <input type="text" name="username" placeholder="Username" />
  <input type="email" name="email" placeholder="Email" />
  <button type="submit">Submit</button>
</form>

集中处理输入验证:

document.getElementById('form').addEventListener('input', (event) => {
    if (event.target.name === 'username') {
        console.log('Validating username...');
    } else if (event.target.name === 'email') {
        console.log('Validating email...');
    }
});

1.5.2 模态框关闭

当需要点击模态框外部区域关闭模态框时,可以通过监听全局 document 的事件,并判断是否点击到了模态框外部。

<div id="modal" style="display: block;">
  <div id="modal-content">
    <p>This is a modal.</p>
  </div>
</div>

关闭模态框的逻辑:

document.addEventListener('click', (event) => {
  const modal = document.getElementById('modal');
  const modalContent = document.getElementById('modal-content');

  if (event.target === modal && !modalContent.contains(event.target)) {
    modal.style.display = 'none';
    console.log('Modal closed');
  }
});

1.6 事件冒泡的优缺点

优点

  1. 减少事件绑定:
  • 使用事件委托时,可以将事件处理程序绑定到父元素,而不是每个子元素,提高性能。
  1. 简化动态元素处理:
  • 动态生成的子元素不需要单独绑定事件,父元素的事件处理程序即可捕获它们的事件。

缺点

  1. 意外触发:
  • 如果不控制好事件冒泡,父元素可能被意外触发,导致逻辑错误。
  1. 调试复杂性:
  • 嵌套事件和冒泡可能导致事件触发顺序难以理解,尤其在嵌套层次较深时。

二、事件委托

2.1 什么是事件委托?

事件委托 是一种事件处理模式,主要利用事件冒泡机制。通过将事件处理程序绑定到父元素,而不是直接绑定到每个子元素,父元素可以捕获并处理其子元素触发的事件。即使子元素是动态生成的,这种方法仍然有效。

2.2 事件委托的核心机制

  1. 事件冒泡机制:
  • 当一个 DOM 元素上的事件被触发时,事件会从目标元素逐层向上冒泡到其祖先元素(直至 document 或 window)。
  • 父元素可以通过捕获冒泡事件并判断事件目标 (event.target) 来执行相应的操作。
  1. 集中管理:
  • 通过将事件处理程序绑定到父元素,可以集中处理子元素的事件,而不需要单独为每个子元素绑定处理程序。

2.3 事件委托基本用法

假设我们有如下 HTML 结构:

<ul id="list">
    <li>Item 1</li>
    <li>Item 2</li>
    <li>Item 3</li>
</ul>
  1. 传统事件绑定

为每个 li 绑定事件:

document.querySelectorAll('#list li').forEach((item) => {
  item.addEventListener('click', () => {
    console.log('Item clicked');
  });
});
  1. 使用事件委托

通过父元素 ul 捕获 li 的点击事件:

document.getElementById('list').addEventListener('click', (event) => {
  if (event.target.tagName === 'LI') {
    console.log('Item clicked:', event.target.textContent);
  }
});

无论 ul 内有多少个 li,只需给父元素 ul 绑定一次事件。父元素捕获到冒泡事件后,通过 event.target 判断事件是由哪个子元素触发的。

2.4 应用场景

因为事件委托依赖于事件冒泡机制,所以事件冒泡的场景即是事件委托场景

2.5 事件委托的优缺点

优点

  1. 减少事件绑定:
  • 无需为每个子元素绑定事件处理程序,可以显著减少事件绑定的数量,从而提升性能。
  • 特别是在有大量子元素时,事件委托的效率更高。
  1. 动态元素支持:
  • 新增的子元素会自动被父元素的事件处理程序捕获,无需重新绑定。
  1. 代码简洁:
  • 集中管理事件逻辑,使代码更清晰、更易维护。

缺点

  1. 目标判断复杂:
  • 父元素需要通过 event.target 判断事件的具体来源,当子元素的层次较多或结构复杂时,逻辑可能变得繁琐。
  1. 不支持不冒泡的事件:
  • 某些事件(如 focus、blur)不支持冒泡,无法使用事件委托。
  1. 父元素过多监听:
  • 如果父元素有大量事件监听逻辑,可能会影响性能。

三、事件冒泡和事件委托的关系

事件委托 依赖 于事件冒泡的机制

  1. 冒泡是实现委托的基础
    事件冒泡将子元素的事件传播到父元素,父元素可以通过监听这些事件并通过 event.target 确定具体的触发子元素,从而处理这些事件。
  2. 委托利用了冒泡机制的特点
    事件委托通过将事件处理程序绑定到父级或更高层级的元素,实现了对子元素事件的集中处理。
  3. 委托的优势得益于冒泡
  • 减少事件绑定数量,提升性能。
  • 父级元素可动态处理新增或删除的子元素的事件。

前端技能树,面试复习第 42 天—— 浏览器原理:事件机制 | 执行栈 | 同步与异步 事件是用户操作网页时发生的交互动作,比如 click/move, 事件除了用户触发的动作外,还可以是文档加载,窗口滚动和大小调整。事件被封装成一个 event 对象,包含了该事件发生时的所有相关信息( event 的属性)以及可以对事件进行的操作( event 的方法)。... 阅读详情

相关推荐

嵌入式开发必备:手把手教你用DB-9连接器搞定RS-232串口通信(附万用表测试技巧)

本文详细解析了嵌入式开发中RS-232串口通信的硬件连接核心。从DB-9连接器的引脚定义入手,深入讲解DTE与DCE设备角色,明确直连线与交叉线的选择法则,并重点分享了使用万用表进行线缆连通性测试、电压测量及故障诊断的实战技巧,帮助开发者彻底掌握串口通信的硬件连接与排查方法。

tgb345678的博客 1166

什么是事件冒泡

什么是事件冒泡 事件冒泡就是指父元素和子元素有相同的事件,当触发子元素事件时,会向上冒泡,同时也会触发父元素事件 事件冒泡的三个阶段 1、捕获阶段:从window对象传导到目标节点(上层传到底层)称为“捕获阶段”,捕获阶段不会响应任何事件; 2、目标阶段:在目标节点上触发称为“目标阶段”; 3、冒泡阶段:从目标节点传导回window对象(从底层传回上层),称为“冒泡阶段”; 事件冒泡的原理 事件委托原理就是利用事件冒泡机制把里层所需要响应的事件绑定到外层 ...

v_jinfuwu的博客 9914

mos管结电容等效模型_MOS管的防冲击防反接电路

MOS管的反接和抑制冲击一:原理分析MOS管由于生产工艺等因素,会产生相应的寄生电容,体二极管等。Mos管的寄生电容如图1所示,可以看到其具有三个寄生电容:G和S的电容Cgs;G和D的电容:Cgd,也称为反向传输电容、米勒电容、Crss;D和S的电容Cds。D和S之间的体二极管D1.图 1:MOS管等效模型寄生电容的数值可以从元器件的datasheet中得到,如图2,图3:Ciss(输入电容)=C...

weixin_29179583的博客 1859

【JavaScript】事件冒泡详解

事件冒泡(Event Bubbling)是指当某个元素上的事件被触发时,该事件会向父级元素传递,直到传递到document对象的过程。在此过程中,所有绑定在这些父级元素上的相同类型的事件处理程序都会依次被触发。这个传递过程就像气泡从水底逐渐向上升一样,因此被称为"冒泡"。事件冒泡是 JavaScript 中非常重要的事件模型,通过它,开发者可以简化事件处理逻辑,尤其是在动态内容和复杂交互中。理解事件冒泡的工作机制和应用场景可以帮助你编写更加高效、易维护的代码。

lph159的博客 4641

Ansys Zemax实战:5步搞定衍射光学元件(DOE)设计,附赠超透镜(metalens)避坑指南

本文详细介绍了使用Ansys Zemax进行衍射光学元件(DOE)和超透镜(metalens)设计的5步实战流程。从基础光学系统搭建到相位面设计验证,再到制造准备与实测对比,全面解析了OpticStudio中的关键技巧和常见避坑指南,帮助工程师高效完成复杂光学元件设计。

orange的博客 622

ros2 humble cartographer 2D激光雷达建图

Cartographer是一个支持多平台和传感器配置的SLAM的系统。 本文主要讲述在ros2 humble系统上cartographer的安装方法,以及如何配置参数实现自己的ros2 bag包的离线建图。

weixin_43087302的博客 6939

浅谈JS事件冒泡

今天要跟大家谈的是事件冒泡,这个事件呢,也是两面性的,有时候给我们带来bug,有时候优点也很明显。我们就一起来看看它的真面目。 首先看看事件冒泡是什么? 事件冒泡 :当一个元素接收到事件的时候 会把他接收到的事件传给自己的父级,一直到window 。(注意这里传递的仅仅是事件 并不传递所绑定的事件函数。所以如果父级没有绑定事件函数,就算传递了事件 也不会有什么表现 ...

aiwu9318的博客 877

DINOv3 网络结构解析:从 ViT 到 ConvNeXt 的双路线设计

本文深入解析了DINOv3网络结构的双路线设计,包括ViT和ConvNeXt两种主干架构。ViT路线通过轴向旋转位置编码解决了传统ViT对固定分辨率的依赖,而ConvNeXt路线则优化了卷积设计,提升了实时处理能力。文章还探讨了Gram Anchoring、混合自监督目标等关键技术,展示了DINOv3在多任务和多模态应用中的强大潜力。

weixin_29214199的博客 564

【 JS 】什么是JavaScript事件冒泡、事件捕获和事件委托

前言 在W3C事件模型中,一次事件的发生包含3个过程 1.捕获: 先由文档的根节点document(window )接收,然后逐级向下传播,直到具体的事件元素 2.目标: 事件源,触发事件 3.冒泡: 与捕获相反,逐级向上,直到文档根节点 (1)可以简单理解为事件发生的顺序不同, (2)绑定事件方法addEventListener(“事件名”,事件function,true),第三个参数默认为fa...

qq_40060547的博客 320

升级最新IDEA版本(2022.1.1)

升级最新IDEA版本(2022.1.1)

软件老王 3万+

萤石云cs刷机解绑固件

萤石CS-C2C-32WFR刷机包,萤石CS-C6TC刷机包,萤石CS-C6H刷机包,萤石猫眼产品等等。萤石云摄像头固件修改,绑定手机号解绑,更换序列号教程。

海康威视技术支持 2万+

JS事件冒泡和事件代理(委托)

事件冒泡 什么是事件冒泡? 当一个元素接收到事件的时候,会把他接收到的事件传给父级,一直传到window (注意这里传递的仅仅是事件 并不传递所绑定的事件函数。所以如果父级没有绑定事件函数,就算传递了事件 也不会有什么表现 但事件确实传递了。) <!DOCTYPE html> <html lang="en"> <head> <meta charse...

菜鸟搬砖记 1万+

关于海康MVS软件显示速率低与1GB、相机丢包的设置优化

工控机主要应用与视觉检测!相机网线及工控机网口都是千兆的!设置完巨帧数和速度与双工(选择为全双工),显示速度低与1GB,不能够正常工作。C.LA-Properdes-Advanced-将RecerveBuffers更改为2048。E.LAN-属性-电源管理-取消选中允许计算机关闭此设备以保存电源。这种情况均为MVS设置不熟悉,可参照如下设置优化相应端口相机配置。D.局域网-属性-高级-将传输缓冲区更改为20484。B.LAN-属性-高级-将中断记录部分更改为执行。A.关闭采集控制帧速率控制。

米可的博客! 8827

js事件冒泡和事件委托

js事件冒泡 js所谓的事件冒泡就是子级元素的某个事件被触发,它的上级元素的该事件也被递归执行 html: <ul class="clearfix" data-type="cityPick"> <li class="active_sort_opts" data-id="0">全部</li> <li data...

aihanguang7682的博客 295

RU DOS版、EFI版32bit/64bit BIOS常用工具

DOS版、EFI版的RU工具,可用来查看IO、MEM、PCI、SMBIOS等资源。亲测在EFI SHELL下可用。

VB摄像头监控

该VB模块可对摄像头捕获的画面进行录像等,可在创建的窗口进行控制

JS事件委托和冒泡

利用 JS 事件冒泡动态为元素绑定事件的方法称为事件委托(Event Delegation,也称为“事件代理”),是 JavaScript 中最热门的技术之一。 事件委托就是把原本需要绑定在子元素上的事件(onclick、onkeydown 等)委托给它的父元素,让父元素来监听子元素的冒泡事件,并在子元素发生事件冒泡时找到这个子元素。 举个简单的例子,整个宿舍的同学都需要去取快递,一种方法是让他们一个个去取,另一种方法是把这件事委托给宿舍长,让宿舍长把所有人的快递都取回来,然后再根据收件人一一分发给宿舍.

hzxOnlineOk的博客 1559

蓝牙模块HM-10手册

蓝牙模块HM-10手册,该手册对蓝牙模块HM-10进行了详细的介绍和使用方法以及一些AT指令。

JS事件冒泡和事件委托

js事件冒泡 js所谓的事件冒泡就是子级元素的某个事件被触发,它的上级元素的该事件也被递归执行 html: <ul class="clearfix" data-type="cityPick"> <li class="active_sort_opts" data-id="0">全部</li> <li data-id="8...

bujiongdan的博客 434

LinePhone3.2.7(android端最新版本) sip客户端

SIP客户端For android:LinePhone3.2.7(最新版本),官网地址:http://www.linphone.org/

js的事件冒泡和事件委托

js事件冒泡 javascript的事件传播过程中,当事件在一个元素上出发之后,事件会逐级传播给先辈元素,直到document为止,有的浏览器可能到window为止,这就是事件冒泡现象。 <div id="col"> <p> <a id="btn" href="#">button</a> </p> <...

qq_41285896的博客 139

js的事件委托和jquery的事件冒泡

js的事件委托和Jquery的事件冒泡处理 事件委托的原理依赖于事件冒泡,可以通过给父元素的事件委托来确定是哪个子元素触发了事件从而做一系列操作。 使用事件委托的优点 **1、**操作子元素时不用一一遍历,可以根据事件触发的对象而进行相应操作 dom结构如下: <ul id = "oUl"> <li class = "item"></li> <li class = "item"></li> <li class = "item">&

cghncgfnm的博客 178

js——事件委托、事件冒泡和事件捕获

在javascript里,事件委托是很重要的一个东西,事件委托依靠的就是事件冒泡和捕获的机制,我先来解释一下事件冒泡和事件捕获: 事件冒泡:从当前触发的事件目标一级一级往上传递,依次触发,直到document为止。 事件捕获:从document开始触发,一级一级往下传递,依次触发,直到真正事件目标为止。 在这里插入代码片asfasdf ...

weixin_40016215的博客 331

55、js事件冒泡和事件委托·

1. 事件冒泡 当一个元素上的事件被触发的时候,同样的事件将会在那个元素的所有祖先元素中被触发。这一过程被称为事件冒泡;这个事件从原始元素开始一直冒泡到DOM树的最上层。

sunnnnh的博客 516

JS的事件冒泡、事件捕获和事件委托

为了提高效率和速度,所以我们这时可以采用事件委托,只给ul绑定一个事件,根据事件冒泡的规则,只要你点了ul里的每一个li,都会触发ul的绑定事件,我们在ul绑定事件的函数里通过一些判断,就可以给这100li都触发点击事件了。我们还是只点击最中间的红色box,和上一次一样,也是三个box都触发了事件,但是顺序反过来了,紫色>绿色>红色,这种现象称为事件捕获。我们仅仅是点击了红色的box,但是绿色和紫色的box也被触发了打印事件,触犯顺序是 红色>绿色>紫色,这种现象就是事件冒泡了。//ie阻止默认事件。

2401_86637363的博客 454

js事件原理、事件委托、事件冒泡和事件绑定 addEventListener

前言 javascript是事件驱动型语言。当用户在网页中进行某种操作时,就产生了一个“事件”(Event)。 事件几乎可以是任何事情:单击一个网页元素、拖动鼠标等均可视为事件。JavaScript是事件驱动的,当事件发生时,它可以对之做出响应。具体如何响应某个事件由编写的事件处理函数完成。 事件基础 事件分为系统派发事件和自定义派发事件。 addEventListener();//事件侦听方法...

蒲公英芽的博客 2006

js_操作dom(委托和冒泡事件)

js操作htmljs操作htmljs操作domdiv绑定js函数js的委托事件js的冒泡事件阻止冒泡方法一方法二方法三 js操作html js操作dom js创建div样式,添加节点删除节点等等 var el1 = document.createElement('div'); var el2 = document.createElement('input'); var node = document.createTextNode('hello world!'); el1.appendChild(el2) e

编程知识分享,主打前端 3万+

JS中事件处理机制(秒懂事件委托、事件捕获和事件冒泡)

因此,如果在某个祖先元素上绑定了事件处理程序,并且该事件处理程序使用了事件捕获阶段,那么该事件处理程序会在目标元素的事件处理程序之前执行。因此,如果在某个祖先元素上绑定了事件处理程序,并且该事件处理程序使用了事件冒泡阶段,那么该事件处理程序会在目标元素的事件处理程序之后执行。因此,当我们将事件处理程序绑定到父元素上时,父元素可以代理处理子元素上的事件,这就是事件委托的原理。综上所述,事件委托利用了事件冒泡的特性来简化事件处理程序的管理和提高性能,而事件捕获相对不常用。,然后分别为它添加了事件监听器。

2401_89285777的博客 1236
上一篇: JavaScript IIFE
有你的星空
博客等级 码龄11年 38粉丝 18原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值