DOM 事件的传播机制

前端面试大全·DOM 事件的传播机制

🌟经典真题

🌟事件与事件流

事件流

事件冒泡流

事件捕获流

标准 DOM 事件流

🌟事件委托

🌟真题解答

🌟总结


🌟经典真题

  • 谈一谈事件委托以及冒泡原理

🌟事件与事件流

事件最早是在 IE3 和 NetscapeNavigator2 中出现的,当时是作为分担服务器运算负担的一种手段。

要实现和网页的互动,就需要通过 JavaScript 里面的事件来实现。

每次用户与一个网页进行交互,例如点击链接,按下一个按键或者移动鼠标时,就会触发一个事件。我们的程序可以检测这些事件,然后对此作出响应。从而形成一种交互。

这样可以使我们的页面变得更加的有意思,而不仅仅像以前一样只能进行浏览。

在早期拨号上网的年代,如果所有的功能都放在服务器端进行处理的话,效率是非常低的。

所以 JavaScript 最初被设计出来就是用来解决这些问题的。通过允许一些功能在客户端处理,以节省到服务器的往返时间。

JavaScript 中采用一个叫做事件监听器的东西来监听事件是否发生。这个事件监听器类似于一个通知,当事件发生时,事件监听器会让我们知道,然后程序就可以做出相应的响应。

通过这种方式,就可以避免让程序不断地去检查事件是否发生,让程序在等待事件发生的同时,可以继续做其他的任务。

事件流

当浏览器发展到第 4 代时(IE4 及 Netscape4),浏览器开发团队遇到了一个很有意思的问题:页面的哪一部分会拥有某个特定的事件?

想象在一张纸上的一组同心圆。如果把手指放在圆心上,那么手指指向的不是一个圆,而是纸上的所有圆。

好在两家公司的浏览器开发团队在看待浏览器事件方面还是一致的。

如果单击了某个按钮,他们都认为单击事件不仅仅发生在按钮上,甚至也单击了整个页面。

但有意思的是,IE 和 Netscape 开发团队居然提出了差不多是完全相反的事件流的概念。

IE 的事件流是事件冒泡流,而 Netscape 的事件流是事件捕获流。

事件冒泡流

IE 的事件流叫做事件冒泡(event bubbling),即事件开始时由最具体的元素(文档中嵌套层次最深的那个节点)接收,然后逐级向上传播到较为不具体的节点(文档)。

以下列 HTML 结构为例,来说明事件冒泡。如下:

<!DOCTYPE html>
<html lang="en"><head><meta charset="UTF-8"><title>Document</title></head><body><div></div></body>
</html>

如果单击了页面中的 div 元素,那么这个 click 事件沿 DOM 树向上传播,在每一级节点上都会发生,按照如下顺序进行传播:

  1. div
  2. body
  3. html
  4. document

所有现代浏览器都支持事件冒泡,但在具体实现在还是有一些差别。

IE9、Firefox、Chrome、Safari 将事件一直冒泡到 window 对象。

我们可以通过下面的代码,来查看文档具体的冒泡顺序,示例如下:

<div id="box" style="height:100px;width:300px;background-color:pink;"></div>
<button id="reset">还原</button>
// IE8 以下浏览器返回 div body html document
// 其他浏览器返回 div body html document window
reset.onclick = function () {history.go();
}
box.onclick = function () {box.innerHTML += 'div\n';
}
document.body.onclick = function () {box.innerHTML += 'body\n';
}
document.documentElement.onclick = function () {box.innerHTML += 'html\n';
}
document.onclick = function () {box.innerHTML += 'document\n';
}
window.onclick = function () {box.innerHTML += 'window\n';
}

在上面的示例中,我们为 div 以及它的祖先元素绑定了点击事件,由于事件冒泡的存在,当我们点击 div 时,所有祖先元素的点击事件也会被触发。

如下图所示:

事件捕获流

Netscape Communicator 团队提出的另一种事件流叫做事件捕获(event captruing)。

事件捕获的思想是不太具体的节点应该更早接收到事件,而最具体的节点应该最后接收到事件。

事件捕获的思想是在事件到达预定目标之前就捕获它。

以同样的 HTML 结构为例来说明事件捕获,如下:

<!DOCTYPE html>
<html lang="en"><head><meta charset="UTF-8"><title>Document</title></head><body><div></div>    </body>
</html>

在事件捕获过程中,document 对象首先接收到 click 事件,然后事件沿 DOM 树依次向下,一直传播到事件的实际目标,即 div 元素:

  1. document
  2. html
  3. body
  4. div

IE9、Firefox、Chrome、Safari 等现代浏览器都支持事件捕获,但是也是从 window 对象开始捕获。

下面我们来演示一个事件捕获流的示例:

<div id="box" style="height:100px;width:300px;background-color:pink;"></div>
<button id="reset">还原</button>
// IE8 以下浏览器不支持
// 其他浏览器返回 window document html body div
reset.onclick = function () {history.go();
}
box.addEventListener('click', function () {box.innerHTML += 'div\n'
}, true)
document.body.addEventListener('click', function () {box.innerHTML += 'body\n';
}, true);
document.documentElement.addEventListener('click', function () {box.innerHTML += 'html\n';
}, true);
document.addEventListener('click', function () {box.innerHTML += 'document\n';
}, true);
window.addEventListener('click', function () {box.innerHTML += 'window\n';
}, true);

在上面的示例中,我们为 div 以及它所有的祖先元素绑定了点击事件,使用的 addEventListener 的方式来绑定的事件,并将第 2 个参数设置为了 true 表示使用事件捕获的方式来触发事件。

效果如下图所示:

标准 DOM 事件流

DOM 标准采用的是捕获 + 冒泡的方式。

两种事件流都会触发 DOM 的所有对象,从 document 对象开始,也在 document 对象结束。

换句话说,起点和终点都是 document 对象(很多浏览器可以一直捕获 + 冒泡到 window 对象)

DOM 事件流示意图:

DOM 标准规定事件流包括三个阶段:事件捕获阶段处于目标阶段事件冒泡阶段

  • **事件捕获阶段:**实际目标 div 在捕获阶段不会触发事件。捕获阶段从 window 开始,然后到 document、html,最后到 body 意味着捕获阶段结束。

  • **处于目标阶段:**事件在 div 上发生并处理,但是本次事件处理会被看成是冒泡阶段的一部分。

  • **冒泡阶段:**事件又传播回文档。

🌟事件委托

上面介绍了事件冒泡流,事件冒泡一个最大的好处就是可以实现事件委托。

事件委托,又被称之为事件代理。在 JavaScript 中,添加到页面上的事件处理程序数量将直接关系到页面整体的运行性能。导致这一问题的原因是多方面的。

首先,每个函数都是对象,都会占用内存。内存中的对象越多,性能就越差。其次,必须事先指定所有事件处理程序而导致的 DOM 访问次数,会延迟整个页面的交互就绪时间。

对事件处理程序过多问题的解决方案就是事件委托。

事件委托利用了事件冒泡,只指定一个事件处理程序,就可以管理某一类型的所有事件。

例如,click 事件会一直冒泡到 document 层次。也就是说,我们可以为整个页面指定一个 onclick 事件处理程序,而不必给每个可单击的元素分别添加事件处理程序。

举一个具体的例子,例如现在我的列表项有如下内容:

<ul id="color-list"><li>red</li><li>yellow</li><li>blue</li><li>green</li><li>black</li><li>white</li>
</ul>

如果我们想把事件监听器绑定到所有的 li 元素上面,这样它们被单击的时候就弹出一些文字,为此我们需要给每一个元素来绑定一个事件监听器。

虽然上面的例子中好像问题也不大,但是想象一下如果这个列表有 100 个元素,那我们就需要添加 100 个事件监听器,这个工作量还是很恐怖的。

这个时候我们就可以利用事件代理来帮助我们解决这个问题。

将事件监听器绑定到父元素 ul 上,这样即可对所有的 li 元素添加事件,如下:

var colorList = document.getElementById("color-list");
colorList.addEventListener("click",function(){alert("Hello");
})

现在我们单击列表中的任何一个 li 都会弹出东西,就好像这些 li 元素就是 click 事件的目标一样。

并且如果我们之后再为这个 ul 添加新的 li 元素的话,新的 li 元素也会自动添加上相同的事件。

但是,这个时候也存在一个问题,虽然我们使用事件代理避免了为每一个 li 元素添加相同的事件,但是如果用户没有点击 li,而是点击的 ul,同样也会触发事件。

这也很正常,因为我们事件就是绑定在 ul 上面的。

此时我们可以对点击的节点进行一个小小的判断,从而保证用户只在点击 li 的时候才触发事件,如下:

var colorList = document.getElementById("color-list");
colorList.addEventListener("click", function (event) {if (event.target.nodeName === 'LI') {alert('点击 li');}
})

🌟真题解答

  • 谈一谈事件委托以及冒泡原理

参考答案:

事件委托,又被称之为事件代理。在 JavaScript 中,添加到页面上的事件处理程序数量将直接关系到页面整体的运行性能。导致这一问题的原因是多方面的。

首先,每个函数都是对象,都会占用内存。内存中的对象越多,性能就越差。其次,必须事先指定所有事件处理程序而导致的 DOM 访问次数,会延迟整个页面的交互就绪时间。

对事件处理程序过多问题的解决方案就是事件委托。

事件委托利用了事件冒泡,只指定一个事件处理程序,就可以管理某一类型的所有事件。例如,click 事件会一直冒泡到 document 层次。也就是说,我们可以为整个页面指定一个 onclick 事件处理程序,而不必给每个可单击的元素分别添加事件处理程序。

事件冒泡(event bubbling),是指事件开始时由最具体的元素(文档中嵌套层次最深的那个节点)接收,然后逐级向上传播到较为不具体的节点(文档)。

🌟总结

本篇文章是关于JavaScript的一道面试题,后续还会持续更新HTML、CSS、JavaScript、Node.js、Vue.js、网络等前端相关面试题。如果文中出现有瑕疵的地方各位通过评论或者私信联系我,我们一起进步,有兴趣的伙伴可以关注订阅: 前端面试题大全  

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/208400.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

如何选择适合长期投资的股票板块?

大家在学习炒股的过程中肯定没少听“板块”这个词&#xff0c;新手可能一脸懵逼&#xff0c;板块到底是啥意思&#xff1f;为什么会有这么多板块&#xff1f; 一、什么是股票板块&#xff1f;常见的板块分类有哪些&#xff1f; 板块理解起来其实很简单&#xff0c;它就是一种分…

用OpenCV与MFC写一个图像格式转换程序

打开不同格式的图形文件&#xff0c;彩色装灰度图像及将其存储为需求格式是图像处理的最基本的操作。如果单纯用MFC编程&#xff0c;是一个令人头痛的事情&#xff0c;有不少的代码量。可用OpenCV与MFC编程就变得相对简单。下面来详细演示这一编程操作。 一 在VS2022中创建一…

第16届中国R会议暨2023X-AGI大会开幕,和鲸科技分享ModelOps在数据科学平台中的实践与应用

11月25日&#xff0c;第 16 届中国 R 会议暨 2023 X-AGI 大会在在中国人民大学逸夫会堂拉开帷幕&#xff0c;本次会议由中国人民大学统计学院、中国人民大学应用统计科学研究中心、统计之都、原灵科技和中国商业统计学会人工智能分会&#xff08;筹&#xff09;主办&#xff0c…

GPT实战系列-大模型训练和预测,如何加速、降低显存

GPT实战系列-大模型训练和预测&#xff0c;如何加速、降低显存 不做特别处理&#xff0c;深度学习默认参数精度为浮点32位精度&#xff08;FP32&#xff09;。大模型参数庞大&#xff0c;10-1000B级别&#xff0c;如果不注意优化&#xff0c;既耗费大量的显卡资源&#xff0c;…

十种接口安全方案!!!

其他系列文章导航 Java基础合集数据结构与算法合集 设计模式合集 多线程合集 分布式合集 ES合集 文章目录 其他系列文章导航 文章目录 前言 一、数据加密&#xff0c;防止报文明文传输。 二、数据加签验签 2.1 什么是加签验签呢&#xff1f; 2.2 有了https等加密数据&am…

Maven总结

文章目录 为什么学习Maven?一、Maven项目架构管理工具二、Maven的下载安装及配置1.maven的下载2.maven目录结构3.配置阿里云镜像和本地仓库:4.maven配置环境变量。5.阿里云镜像和本地仓库说明 三、idea中maven的操作1.以模板的形式创建maven项目2.其他配置maven的方式3.不勾模…

从图片或PDF文件识别表格提取内容的简单库img2table

img2table是一个基于OpenCV 图像处理的用于 PDF 和图像的表识别和提取 Python库。由于其设计基于神经网络的解决方案&#xff0c;提供了一种实用且更轻便的替代方案&#xff0c;尤其是在 CPU 上使用时。 该库的特点&#xff1a; 识别图像和PDF文件中的表格&#xff0c;包括在表…

Windows微软常用运行库合集2023

微软常用运行库合集适用于Windows系统的运行库合集包&#xff0c;基于微软官方的运行库而制作的&#xff0c;包括了常用的vb&#xff0c;vc2005/2008/2010/2012/2013/2017/2019/2005-2022&#xff0c;Microsoft Universal C Runtime&#xff0c;VS 2010 Tools For Office Runti…

智慧工地一体化解决方案(里程碑管理)源码

智慧工地为管理人员提供及时、高效、优质的远程管理服务&#xff0c;提升安全管理水平&#xff0c;确保施工安全提高施工质量。实现对人、机、料、法、环的全方位实时监控&#xff0c;变被动“监督”为主动“监控”。 一、建设背景 施工现场有数量多、分布广&#xff0c;总部统…

软件工程--面向对象分析用通俗语言20小时爆肝总结!(包含用例图、活动图、类图、时序图......)

面向对象方法分为面向对象分析&#xff08;OOA&#xff09;、面向对象设计&#xff08;OOD&#xff09;、面向对象编程&#xff08;OOP&#xff09;&#xff0c;本文详细介绍面向对象分析 本文参考教材&#xff1a;沈备军老师的《软件工程原理》大多图片来源其中 目录 面向对…

docker部署frp穿透内网

文章目录 &#xff08;1&#xff09;部署frps服务器&#xff08;2&#xff09;部署frpc客户端&#xff08;3&#xff09;重启与访问frp&#xff08;4&#xff09;配置nginx反向代理 &#xff08;1&#xff09;部署frps服务器 docker安装参考文档&#xff1a;docker基本知识 1…

亚马逊云科技re:Invent大会,助力安全构建规模化生成式AI应用

2023亚马逊云科技re:Invent全球大会进入第三天&#xff0c;亚马逊云科技数据和人工智能副总裁Swami Sivasubramanian博士在周三的主题演讲中&#xff0c;为大家带来了关于亚马逊云科技生成式AI的最新能力、面向生成式AI时代的数据战略以及借助生成式AI应用提高生产效率的精彩分…

基于机器深度学习的交通标志目标识别

在线工具推荐&#xff1a; 三维数字孪生场景工具 - GLTF/GLB在线编辑器 - Three.js AI自动纹理化开发 - YOLO 虚幻合成数据生成器 - 3D模型在线转换 - 3D模型预览图生成服务 智能交通系统&#xff08;ITS&#xff09;&#xff0c;包括无人驾驶车辆&#xff0c;尽管在道路…

【云备份】业务处理

文章目录 1. 业务处理作用功能 2. 代码框架编写构造函数UpLoad ——文件上传请求ListShow —— 展示页面请求处理实现Download —— 下载请求的处理实现断点续传实现 1. 业务处理 作用 业务处理模块是对客户端的业务请求进行处理 功能 1.文件上传请求&#xff1a;备份客户端…

数据库管理-第120期 初探Halo数据库(202301201)

数据库管理-第120期 初探Halo数据库&#xff08;202301201&#xff09; 12月份正好也是第120期&#xff0c;新的一篇文章&#xff0c;尝试一条新的路线。其实吧&#xff0c;Halo&#xff08;羲和&#xff09;这个数据库我较早时间就听说过&#xff08;早于今年DTCC&#xff0c…

Glide结合OkHttp保证短信验证接口携带图形验证码接口返回Cookie值去做网络请求

一、实现效果 二、步骤 注意&#xff1a;仅展示核心部分代码 1、导入依赖 api com.github.bumptech.glide:glide:4.10.0 kapt com.github.bumptech.glide:compiler:4.10.0 api com.squareup.okhttp3:okhttp:3.11.0 api com.squareup.okhttp3:logging-interceptor:3.11.02、自…

【EMFace】《EMface: Detecting Hard Faces by Exploring Receptive Field Pyramids》

arXiv-2021 文章目录 1 Background and Motivation2 Related Work3 Advantages / Contributions4 Method5 Experiments5.1 Datasets and Metrics5.2 Ablation Study5.3 Comparison with State-of-the-Arts 6 Conclusion&#xff08;own&#xff09; 1 Background and Motivatio…

腾讯云云服务器功能与优势

腾讯云云服务器&#xff08;Cloud Virtual Machine&#xff0c;CVM&#xff09;是腾讯云提供的可扩展的计算服务。使用云服务器 CVM 避免了使用传统服务器时需要预估资源用量及前期投入的问题&#xff0c;帮助您在短时间内快速启动任意数量的云服务器并及时部署应用程序。 云服…

<软考>软件设计师-1计算机组成与结构(总结)

(一)计算机系统基础知识 1 计算机硬件组成 计算机的基本硬件系统由运算器、控制器、存储器、输入设备 和 输出设备 5大部件组成。 1 运算器、控制器等部件被集成在一起统称为中央处理单元(CPU) 。CPU是硬件系统的核心&#xff0c;用于数据的加工处理&#xff0c;能完成各种算…

Linux系统安装Docker-根据官方教程教程(以Ubuntu为例)

Linux系统安装Docker-根据官方教程教程&#xff08;以Ubuntu为例&#xff09; 1. 背景介绍2. 环境配置2.1 软件环境要求2.2 软件下载2.3 文档地址2.3 必备命令工具下载 3. 安装Docker3.1 使用root用户操作后续命令3.2 卸载可能存在的旧版本 4. 安装Docker4.1 更新依赖包4.2 配置…