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 树向上传播,在每一级节点上都会发生,按照如下顺序进行传播:
- div
- body
- html
- 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 元素:
- document
- html
- body
- 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、网络等前端相关面试题。如果文中出现有瑕疵的地方各位通过评论或者私信联系我,我们一起进步,有兴趣的伙伴可以关注订阅: 前端面试题大全
相关文章:

DOM 事件的传播机制
前端面试大全DOM 事件的传播机制 🌟经典真题 🌟事件与事件流 事件流 事件冒泡流 事件捕获流 标准 DOM 事件流 🌟事件委托 🌟真题解答 🌟总结 🌟经典真题 谈一谈事件委托以及冒泡原理 dz…...

(数据结构)顺序表的查找
静态分配代码: #include<stdio.h> #include<stdlib.h> #define MAX 100 typedef struct LinkList {int data[MAX];int lenth; }Link; //初始化 void CreateList(Link* L) {L->lenth 0;for (int i 0; i < MAX; i){L->data[i] 0;} } //插入 …...

vue 解决响应大数据表格渲染崩溃问题
如果可以实现记得点赞分享,谢谢老铁~ 1.场景描述 发起请求获取上万条数据,进行表格渲染,使浏览器卡顿,导致网页崩溃。 2.分析原因 1.大量数据加载,过多操作Dom,消耗性能。 2.表格中包含其他…...

Hdoop学习笔记(HDP)-Part.13 安装Ranger
目录 Part.01 关于HDP Part.02 核心组件原理 Part.03 资源规划 Part.04 基础环境配置 Part.05 Yum源配置 Part.06 安装OracleJDK Part.07 安装MySQL Part.08 部署Ambari集群 Part.09 安装OpenLDAP Part.10 创建集群 Part.11 安装Kerberos Part.12 安装HDFS Part.13 安装Ranger …...

Spring AOP记录接口访问日志
Spring AOP记录接口访问日志 介绍应用范围组成通知(Advice)连接点(JoinPoint)切点(Pointcut)切面(Aspect)引入(Introduction)织入(Weaving&#x…...

分享89个节日PPT,总有一款适合您
分享89个节日PPT,总有一款适合您 89个节日PPT下载链接:https://pan.baidu.com/s/1j6Yj-7UCcUyV4V_S_eGjpQ?pwd6666 提取码:6666 Python采集代码下载链接:采集代码.zip - 蓝奏云 学习知识费力气,收集整理更不易…...
PostgreSQL日志中的SQL记录时机 —— log_statement 和 log_min_duration_statement
最近跟朋友讨论到PostgreSQL日志中的SQL记录时机,研究了下log_statement 和 log_min_duration_statement两个参数,记录一下。 一、 参数简介 1. log_statement ① 作用 控制记录SQL的类型,可选值为: none:关闭&…...

Agent举例与应用
什么是Agent OpenAI 应用研究主管 Lilian Weng 在一篇长文中提出了 Agent LLM(大型语言模型)记忆规划技能工具使用这一概念,并详细解释了Agent的每个模块的功能。她对Agent未来的应用前景充满信心,但也表明到挑战无处不在。 现…...

CentOS 7 配置tomcat
简介 Tomcat是一个使用Java编写的开源Web应用服务器,是由Apache Software Foundation管理的一个项目。它是一个轻量级的应用服务器,可以下载、安装和使用,而且还提供了许多高级功能,例如支持Java Servlet、JavaServer Pages (JSP)和JavaServer Faces (JSF) 等JavaEE技术,…...
如何优雅的关闭一个IIS站点
众所周知,当我们使用IIS的时候,在使用负载均衡的情况下,想停掉一个站点,通常会点击Sites(网站)中的Stop(停止)来停止一个站点。但是这样做,会带来一个问题,当…...

弱网模拟工具
一、背景 一个人晚上在家通过 Wi-Fi 上网,在线电影播放基本流畅,可一旦在晚间用网高峰期打视频电话就画面糊,这时不仅可能带宽受限了,还可能有较高的丢包率。与有线网络通信相比,无线网络通信受环境影响会更大&#x…...
Leetcode 第 110 场双周赛 Problem D 2809. 使数组和小于等于 x 的最少时间(DP+贪心+正难则反)
Leetcode 第 110 场双周赛 Problem D 2809. 使数组和小于等于 x 的最少时间(DP 好题)题目 给你两个长度相等下标从 0 开始的整数数组 nums1 和 nums2 。每一秒,对于所有下标 0 < i < nums1.length ,nums1[i] 的值都增加 num…...

已知数组A[1..n]中元素类型为非负整数,设计算法将其调整为左右两部分,左边所有为奇数,右边所有为偶数,并要求算法的时间复杂度为O(n)
//左边奇数右边偶数 void Swap(int* a, int* b) {int tmp *b;*b *a;*a tmp; } void LeftRight(int arr[],int n) {int i 0;int j n - 1;while(i<j){if (arr[i] % 2 0 && arr[j] % 2 1) {Swap(&arr[i], &arr[j]);i;j--;}else if (arr[i] % 2 1 &…...

ssm+vue的罪犯信息管理系统(有报告)。Javaee项目,ssm vue前后端分离项目。
演示视频: ssmvue的罪犯信息管理系统(有报告)。Javaee项目,ssm vue前后端分离项目。 项目介绍: 采用M(model)V(view)C(controller)三层体系结构&…...
Java/Android 各类型数据构造和各类型数据解析
Java/Android 各类型数据构造和各类型数据解析 1.如何构造/解析{"key":"value","key":"value","key":"value"}jsonString1)json解析2)fastjson解析3)Gson解析4)遍历key值解析2.如何构造/解析[{"key&q…...

Linux系统---环境变量+内核进程调度队列(选学)
顾得泉:个人主页 个人专栏:《Linux操作系统》 《C/C》 《LeedCode刷题》 键盘敲烂,年薪百万! 一、环境变量 1.基本概念 环境变量(environment variables)一般是指在操作系统中用来指定操作系统运行环境的一些参数,…...
Kubernetes 使用插件扩展 kubectl
例子演示 编写 kubectl-foo ,拷贝至 /usr/local/bin/ #!/bin/bash# 可选的参数处理 if [[ "$1" "version" ]] thenecho "1.0.0"exit 0 fi# 可选的参数处理 if [[ "$1" "config" ]] thenecho $KUBECONFIGexit…...
前端面试题09
74、定义类的方法有哪些 在JavaScript中,定义类的方法有以下几种方式: 1.使用函数声明: function MyClass() {// constructor } MyClass.prototype.methodName function() {// method body };2.使用类的方法缩写(ES6引入&…...

网站更换IP的四大注意事项
1.对网站当中的数据进行备份 网站更换IP时可以将页面的数据库文件和站点文件通过下载工具在本地完成备份。 2.更换解析域名 从站点域名管理后台当中更换域名地址,改为新的IP地址。 3.确保IP安全 在用户更换IP前一定要确定IP是否安全,一旦IP存在不良…...

策略模式与简单工厂模式:终结if-else混乱,让代码更清爽
阅读建议 嗨,伙计!刷到这篇文章咱们就是有缘人,在阅读这篇文章前我有一些建议: 本篇文章大概4500多字,预计阅读时间长需要5分钟。本篇文章的实战性、理论性较强,是一篇质量分数较高的技术干货文章&#x…...
Python爬虫实战:研究MechanicalSoup库相关技术
一、MechanicalSoup 库概述 1.1 库简介 MechanicalSoup 是一个 Python 库,专为自动化交互网站而设计。它结合了 requests 的 HTTP 请求能力和 BeautifulSoup 的 HTML 解析能力,提供了直观的 API,让我们可以像人类用户一样浏览网页、填写表单和提交请求。 1.2 主要功能特点…...

Linux应用开发之网络套接字编程(实例篇)
服务端与客户端单连接 服务端代码 #include <sys/socket.h> #include <sys/types.h> #include <netinet/in.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <arpa/inet.h> #include <pthread.h> …...
OpenLayers 可视化之热力图
注:当前使用的是 ol 5.3.0 版本,天地图使用的key请到天地图官网申请,并替换为自己的key 热力图(Heatmap)又叫热点图,是一种通过特殊高亮显示事物密度分布、变化趋势的数据可视化技术。采用颜色的深浅来显示…...
服务器硬防的应用场景都有哪些?
服务器硬防是指一种通过硬件设备层面的安全措施来防御服务器系统受到网络攻击的方式,避免服务器受到各种恶意攻击和网络威胁,那么,服务器硬防通常都会应用在哪些场景当中呢? 硬防服务器中一般会配备入侵检测系统和预防系统&#x…...

ESP32 I2S音频总线学习笔记(四): INMP441采集音频并实时播放
简介 前面两期文章我们介绍了I2S的读取和写入,一个是通过INMP441麦克风模块采集音频,一个是通过PCM5102A模块播放音频,那如果我们将两者结合起来,将麦克风采集到的音频通过PCM5102A播放,是不是就可以做一个扩音器了呢…...
数据库分批入库
今天在工作中,遇到一个问题,就是分批查询的时候,由于批次过大导致出现了一些问题,一下是问题描述和解决方案: 示例: // 假设已有数据列表 dataList 和 PreparedStatement pstmt int batchSize 1000; // …...
CRMEB 框架中 PHP 上传扩展开发:涵盖本地上传及阿里云 OSS、腾讯云 COS、七牛云
目前已有本地上传、阿里云OSS上传、腾讯云COS上传、七牛云上传扩展 扩展入口文件 文件目录 crmeb\services\upload\Upload.php namespace crmeb\services\upload;use crmeb\basic\BaseManager; use think\facade\Config;/*** Class Upload* package crmeb\services\upload* …...

select、poll、epoll 与 Reactor 模式
在高并发网络编程领域,高效处理大量连接和 I/O 事件是系统性能的关键。select、poll、epoll 作为 I/O 多路复用技术的代表,以及基于它们实现的 Reactor 模式,为开发者提供了强大的工具。本文将深入探讨这些技术的底层原理、优缺点。 一、I…...
全面解析各类VPN技术:GRE、IPsec、L2TP、SSL与MPLS VPN对比
目录 引言 VPN技术概述 GRE VPN 3.1 GRE封装结构 3.2 GRE的应用场景 GRE over IPsec 4.1 GRE over IPsec封装结构 4.2 为什么使用GRE over IPsec? IPsec VPN 5.1 IPsec传输模式(Transport Mode) 5.2 IPsec隧道模式(Tunne…...

回溯算法学习
一、电话号码的字母组合 import java.util.ArrayList; import java.util.List;import javax.management.loading.PrivateClassLoader;public class letterCombinations {private static final String[] KEYPAD {"", //0"", //1"abc", //2"…...