前端JavaScript-嵌套事件
点击
如果在多层嵌套中,对每层都设置事件监视器,试试看
<!DOCTYPE html>
<html lang="cn">
<body><div id="container"><button>点我!</button></div><pre id="output"></pre><script src="button.js"></script>"
</body>
</html>
const output = document.querySelector("#output");
const container = document.querySelector("#container");
const button = document.querySelector("button");function handleClick(e) {output.textContent += `你在 ${e.currentTarget.tagName} 元素上进行了点击\n`;
}document.body.addEventListener("click", handleClick);
container.addEventListener("click", handleClick);
button.addEventListener("click", handleClick);
在 JS 脚本中先用 querySelector (querySelector是JS原生提供的DOM元素查找函数,是DOM API中的一部分,它的作用是通过 CSS选择器 定位匹配的第一个元素)来确定了 output 和 container 位置并赋值给变量
(CSS选择器通过特定语法匹配HTML元素并应用样式,通过 .class 、 #id ,将其应用到JS里面来提取元素的好处就是不用更改语法)
接着设置了自定义函数 handleClick(e) ,参数e是一个事件对象(Event object),这是浏览器自动传递给事件处理函数的一个参数,比如 button.addEventListener("click", handleClick); 这告诉了如果点击了button那么就调用 handleClick,这时会自动生成一个事件对象,其中 e.currentTarget 就是监听对象 button ,而 e.currentTarget.tagName 就是 事件监听器对象元素的标签名
这个事件并不是通过 alert 实现输出,而是直接更改 DOM元素output 的值,这会在点击后直接显示
你在 BUTTON 元素上进行了点击
你在 DIV 元素上进行了点击
你在 BODY 元素上进行了点击
可以看到三层元素都触发了单击事件
可以观察到
最先触发的是按钮的
然后是其父元素...
可以理解为:事件从点击的最里层的元素冒泡而出
.target 和 .currentTarget 有什么区别
event.target 和 event.currentTarget 都指向DOM元素,但是
event.target 指向的是触发事件的元素,在冒泡过程中是保持不变的
event.currentTarget 指向的是事件处理程序当前附加到的元素,也就是当前处理层的元素
注册而非轮询
也许你会好奇,为什么我都没有加 while ,我一旦触发事件还是会有相应的结果呢?
其实事件监视器是被动的、称为“事件驱动程序”的模式
在浏览器内部有一个事件循环机制,它会不断地持续检查队列中是否有事件要处理
异步处理:当用户触发事件时,浏览器会将这个事件放入事件队列,事件循环一旦检测到队列中有事件就会用相应的事件处理(异步处理是一种编程和系统设计模式,其核心在于非阻塞执行,在发起耗时操作,如IO、网络请求等后,程序不会等待操作完成,而是继续执行后续任务,等操作完成再回调
(不阻塞:不会阻塞主线程或消耗CPU资源来主动检查事件是否发生,只有事件触发时相关代码才会执行)
在线程、线程池、异步-CSDN博客有更详细说明
隐藏
我们想要实现隐藏视频,只有在点击按钮的时候才显现,这时候点击视频会开始播放,点击除视频外的地方会隐藏视频
<button>显示视频</button><div class="hidden"><video><source src="/shared-assets/videos/flower.webm" type="video/webm" /><p>你的浏览器不支持 HTML 视频,这里有视频的<a href="rabbit320.mp4">替代链接</a>。</p></video>
</div>
const btn = document.querySelector("button");
const box = document.querySelector("div");
const video = document.querySelector("video");btn.addEventListener("click", () => box.classList.remove("hidden"));
video.addEventListener("click", () => video.play());
box.addEventListener("click", () => box.classList.add("hidden"));
在 JS 里面添加了三个 'click' 事件处理器
classList 是 DOM 元素对象的一个属性,提供了一个便捷的方式来操作元素的类(class属性),它是 DOMTokenList 类型的对象,用于添加、删除、检查和切换 CSS 类
button 的点击处理器会通过 box 的 classList 移除 div 的 "hidden" 类
在运行的时候会发现点击按钮的时候会显示视频,但是点击视频的时候盒子又被隐藏了,这是因为 video 在 div 里面,所以点击视频会触发 video 的事件,也会触发 div 的事件
这时候我们就想要阻止 video 向外界的感染,需要通过 stopPropagation( ) 方法
const btn = document.querySelector("button");
const box = document.querySelector("div");
const video = document.querySelector("video");btn.addEventListener("click", () => box.classList.remove("hidden"));video.addEventListener("click", (event) => {event.stopPropagation();video.play();
});box.addEventListener("click", () => box.classList.add("hidden"));
可以看到我们在 video 的事件里面添加了 event.stopPropagation();
事件捕捉
跟冒泡顺序相反,从最外层到最里面,想实现这样的操作只需要将 capture 参数设置为 true
比如刚开始的按钮例子
document.body.addEventListener("click", handleClick, { capture: true });
container.addEventListener("click", handleClick, { capture: true });
button.addEventListener("click", handleClick);
顺序就发生了颠倒
你在 BODY 元素上进行了点击
你在 DIV 元素上进行了点击
你在 BUTTON 元素上进行了点击
事件委托
默认冒泡的话,我们可以通过子元素感染父元素,而不用一个个设置了,不直接在子元素上设置监听器,而是将监听器设置在父元素上,通过冒泡让父元素监听来自子元素的事件,
<!DOCTYPE html>
<html lang="en"></html>
<body><link href="button.css" rel="stylesheet" type="text/css"><div id="container"><div class="tile"></div><div class="tile"></div><div class="tile"></div><div class="tile"></div><div class="tile"></div><div class="tile"></div><div class="tile"></div><div class="tile"></div><div class="tile"></div><div class="tile"></div><div class="tile"></div><div class="tile"></div><div class="tile"></div><div class="tile"></div><div class="tile"></div><div class="tile"></div></div><script src="button.js"></script>"
</body>
</html>
.tile {height: 100px;width: 25%;float: left;
}
function random(number) {return Math.floor(Math.random() * number);
}function bgChange() {const rndCol = `rgb(${random(255)}, ${random(255)}, ${random(255)})`;return rndCol;
}const container = document.querySelector("#container");container.addEventListener("click", (event) => {event.target.style.backgroundColor = bgChange();
});
在这个例子中有很多 .title 元素在 #container 内
但是没有对每个元素添加事件监听器
而是在父元素 #container 上加了监听器,通过 event.target 来确定是哪个子元素触发了事件,并更改其 style.backgroundColor 为 bgChange
相关文章:
前端JavaScript-嵌套事件
点击 如果在多层嵌套中,对每层都设置事件监视器,试试看 <!DOCTYPE html> <html lang"cn"> <body><div id"container"><button>点我!</button></div><pre id"output…...

X 下载器 2.1.42 | 国外媒体下载工具 网页视频嗅探下载
X 下载器让你能够轻松地从社交应用如Facebook、Instagram、TikTok等下载视频和图片。通过内置浏览器访问网站,它能自动检测视频和图片,只需点击下载按钮即可完成下载。去除广告,解锁本地会员,享受无广告打扰的下载体验。 大小&am…...

STM32 CAN CANAerospace
STM32的CAN模块对接CANAerospace 刚开始报错如下. 设备开机后整个CAN消息就不发了. USB_CAN调试器报错如下. index time Name ID Type Format Len Data00000001 000.000.000 Event 总线错误 DATA STANDARD 8 接收过程错误-格…...

完整改进RIME算法,基于修正多项式微分学习算子Rime-ice增长优化器,完整MATLAB代码获取
1 简介 为了有效地利用雾状冰生长的物理现象,最近开发了一种优化算法——雾状优化算法(RIME)。它模拟硬雾状和软雾状过程,构建硬雾状穿刺和软雾状搜索机制。在本研究中,引入了一种增强版本,称为修改的RIME…...

服务器安装xfce桌面环境并通过浏览器操控
最近需要运行某个浏览器的脚本,但是服务器没有桌面环境,无法使用,遂找到了KasmVNC,并配合xfce实现低占用的桌面环境,可以直接使用浏览器进行操作 本文基于雨云——新一代云服务提供商的Debian11服务器操作,…...
Java设计模式之组合模式:从入门到精通(保姆级教程)
文章目录 1. 组合模式概述1.1 专业定义1.2 通俗解释1.3 模式结构2. 组合模式详细解析2.1 模式优缺点2.2 适用场景3. 组合模式实现详解3.1 基础实现3.2 代码解析4. 组合模式进阶应用4.1 透明式 vs 安全式组合模式4.2 组合模式与递归4.3 组合模式与迭代器5. 组合模式在实际开发中…...

Oracle 创建外部表
找别人要一下数据,但是他发来一个 xxx.csv 文件,怎么办? 1、使用视图化工具导入 使用导入工具导入,如 DBeaver,右击要导入的表,选择导入数据。 选择对应的 csv 文件,下一步就行了(如…...

大语言模型 17 - MCP Model Context Protocol 介绍对比分析 基本环境配置
MCP 基本介绍 官方地址: https://modelcontextprotocol.io/introduction “MCP 是一种开放协议,旨在标准化应用程序向大型语言模型(LLM)提供上下文的方式。可以把 MCP 想象成 AI 应用程序的 USB-C 接口。就像 USB-C 提供了一种…...

【软考向】Chapter 9 数据库技术基础
基本概念数据库的三级模式结构 数据模型E-R 模型关系模型各种键完整性约束 关系代数5 种基本的关系代数运算:并、差、笛卡儿积、投影和选择扩展的关系代数运算:交(Intersection)、连接(Join)、除(Division)、广义投影(Generalized Projection)、外连接(O…...

实战:Dify智能体+Java=自动化运营工具!
我们在运营某个圈子的时候,可能每天都要将这个圈子的“热门新闻”发送到朋友圈或聊天群里,但依靠传统的实现手段非常耗时耗力,我们通常要先收集热门新闻,再组装要新闻内容,再根据内容设计海报等。 那怎么才能简化并高…...

STM32单片机GUI系统1 GUI基本内容
目录 一、GUI简介 1、emWin 2、LVGL (Light and Versatile Graphics Library) 3、TouchGFX 4、Qt for Embedded 5、特性对比总结 二、LVGL移植要求 三、优化LVGL运行效果方法 四、LVGL系统文件 一、GUI简介 在嵌入式系统中,emWin、LVGL、TouchGFX 和 Qt 是…...
从零开始学习three.js(21):一文详解three.js中的矩阵Matrix和向量Vector
一、三维世界的数学基石 在Three.js的三维世界里,所有视觉效果的实现都建立在严密的数学基础之上。其中向量(Vector) 和矩阵(Matrix) 是最核心的数学工具,它们就像构建数字宇宙的原子与分子,支…...

应届本科生简历制作指南
一、找一个专业的简历模板 首先,你需要访问 Overleaf 的官方网站,也就是Overleaf, Online LaTeX Editor,进入页面后,点击注册按钮,按照提示填写相关信息来创建一个属于自己的账号,通常需要填写用户名、邮箱…...
VUE3+TS实现图片缩放移动弹窗
完整代码 使用VUE3、TS,实现将图片通过鼠标拖拽缩放以及选择缩放比例。 <template><div><el-dialogv-model"dialogVisible"title"查看图片":close-on-click-modal"false":close-on-press-escape"false"fu…...
大语言模型训练数据格式:Alpaca 和 ShareGPT
在大规模语言模型(LLM)的开发中,训练数据的质量和格式起着至关重要的作用。为了更好地理解和构建高质量的数据集,社区发展出了多种标准化的数据格式。其中,Alpaca 和 ShareGPT 是两种广泛使用的训练数据格式࿰…...
实现动态增QuartzJob,通过自定义注解调用相应方法
:::tip 动态增加Quartz定时任务,通过自定义注解来实现具体的定时任务方法调用。 ::: 相关依赖如下 <!-- 用来动态创建 Quartz 定时任务 --> <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-start…...

PyTorch可视化工具——使用Visdom进行深度学习可视化
文章目录 前置环境Visdom安装并启动VisdomVisdom图形APIVisdom静态更新API详解通用参数说明使用示例Visdom动态更新API详解1. 使用updateappend参数2. ~~使用vis.updateTrace方法~~3. 完整训练监控示例 Visdom可视化操作散点图plot.scatter()散点图案例线性图vis.line()vis.lin…...
Qt无边框界面添加鼠标事件
在Qt中实现无边框窗口的鼠标事件处理,主要涉及窗口拖动和调整大小功能。以下是分步实现的代码示例: 1. 创建无边框窗口 首先,创建一个继承自QWidget的自定义窗口类,并设置无边框标志: #include <QWidget> #in…...

企业级爬虫进阶开发指南
企业级爬虫进阶开发指南 一、分布式任务调度系统的深度设计 1.1 架构设计原理 图表 1.2 核心代码实现与注释 分布式锁服务 # distributed_lock.py import redis import timeclass DistributedLock:def __init__(self, redis_conn):self.redis = redis_connself.lock_key = …...
Ubuntu ping网络没有问题,但是浏览器无法访问到网络
我这边是尝试清楚DNS缓存然后重新访问就可以了。 使用 resolvectl 刷新 DNS 缓存 在 Ubuntu 20.04 及更高版本中,可以使用以下命令来刷新 DNS 缓存: sudo resolvectl flush-caches 使用 systemd-resolve(适用于旧版本) 如果你…...

网络安全-等级保护(等保) 2-7 GB/T 25058—2019 《信息安全技术 网络安全等级保护实施指南》-2019-08-30发布【现行】
################################################################################ GB/T 22239-2019 《信息安全技术 网络安全等级保护基础要求》包含安全物理环境、安全通信网络、安全区域边界、安全计算环境、安全管理中心、安全管理制度、安全管理机构、安全管理人员、安…...

数据结构实验10.1:内部排序的基本运算
文章目录 一,实验目的二,实验内容1. 数据生成与初始化2. 排序算法实现(1)直接插入排序(2)二分插入排序(3)希尔排序(4)冒泡排序(5)快速…...
C#:多线程
一.线程常用概念 线程(Thread):操作系统执行程序的最小单位 进程(Process):程序在内存中的运行实例 并发(Concurrency):多个任务交替执行(单核CPU࿰…...
基于Zynq SDK的LWIP UDP组播开发实战指南
一、为什么选择LWIP组播? 在工业控制、智能安防、物联网等领域,一对多的高效数据传输需求日益增长。Zynq-7000系列SoC凭借其ARM+FPGA的独特架构,结合LWIP轻量级网络协议栈,成为嵌入式网络开发的理想选择。本文将带您实现: LWIP组播配置全流程动态组播组切换技术零拷贝数据…...
c#将json字符串转换为对象数组
在C#中,将JSON字符串转换为对象数组是一个常见的需求,特别是在处理来自Web API的响应或需要反序列化本地文件内容时。这可以通过使用Newtonsoft.Json(也称为Json.NET)库或.NET Core内置的System.Text.Json来完成。以下是如何使用这…...
机器学习在智能水泥基复合材料中的应用与实践
“机器学习在智能水泥基复合材料中的应用与实践” 课程 内容 机器学习基础模型与复合材料研究融合 机器学习在复合材料中的应用概述机器学习用于复合材料研究的流程复合材料数据收集与数据预处理 实例:数据的收集和预处理 复合材料机器学习特征工程与选择 实例&a…...

wps编辑技巧
1、编辑模式 2、图片提取方法:右键保存图片 可以直接右键保存下来看看是否是原始图,如果歪着的图,可能保存下来是正的,直接保存试下 3、加批注...

开放世界RPG:无缝地图与动态任务的拓扑学架构
目录 开放世界RPG:无缝地图与动态任务的拓扑学架构引言第一章 地图分块系统1.1 动态加载算法1.2 内存管理模型第二章 任务拓扑网络2.1 任务依赖图2.2 动态可达性分析第三章 NPC行为系统3.1 行为森林架构3.2 日程规划算法第四章 动态事件系统4.1 事件传播模型4.2 玩家影响指标第…...

【图像处理入门】1. 数字图像的本质:从像素到色彩模型
作为图像处理的开篇,本文将带你拆解数字图像的底层逻辑:从模拟图像到数字信号的神奇转换,到像素世界的微观构成,再到彩色图像的编码奥秘。通过 Python 代码实战,你将亲手触摸图像的 “基因”—— 像素值,并…...

(已解决:基于WSL2技术)Windows11家庭中文版(win11家庭版)如何配置和使用Docker Desktop
目录 问题现象: 问题分析: 拓展: 解决方法: 1、使用WSL2技术(亲测有效) 注意: 2、开启Hyper-V功能(未经亲测,待研究) 问题现象: 今天想在本…...