前端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

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

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

相关文章

网感驱动下开源AI大模型AI智能名片S2B2C商城小程序源码的实践路径研究

摘要&#xff1a;在数字化浪潮中&#xff0c;网感已成为内容创作者与商业运营者必备的核心能力。本文以开源AI大模型、AI智能名片及S2B2C商城小程序源码为技术载体&#xff0c;通过解析网感培养与用户需求洞察的内在关联&#xff0c;提出"数据驱动-场景适配-价值重构"…

AG-UI:重构AI代理与前端交互的下一代协议标准

目录 技术演进背景与核心价值协议架构与技术原理深度解析核心功能与标准化事件体系典型应用场景与实战案例开发者生态与集成指南行业影响与未来展望1. 技术演进背景与核心价值 1.1 AI交互的三大痛点 当前AI应用生态面临三大核心挑战: 交互碎片化:LangGraph、CrewAI等框架各…

游戏引擎学习第301天:使用精灵边界进行排序

回顾并为今天的内容做准备 昨天&#xff0c;我们解决了一些关于排序的问题&#xff0c;这对我们清理长期存在的Z轴排序问题很有帮助。这个问题我们一直想在开始常规游戏代码之前解决。虽然不确定是否完全解决了问题&#xff0c;但我们提出了一个看起来合理的排序标准。 有两点…

Ajax快速入门教程

输入java时&#xff0c;页面并没有刷新但是下面自动联想出了跟java有关的东西&#xff0c;像这种就叫异步交互 它不会妨碍你的输入&#xff0c;同时还能够同步进行对于java相关联想词的推送 发送异步请求需要借助工具axios 引入axios&#xff0c;可以直接在scripts中引入 get和…

Anti Spy安卓版:智能防护,守护手机安全

Anti Spy安卓版是一款专为安卓设备设计的智能防护应用&#xff0c;旨在帮助用户实时防护手机安全&#xff0c;抵御间谍软件、恶意软件和其他潜在威胁。它基于人工智能和启发式搜索方法的引擎&#xff0c;能够检测并阻止已知和未知的间谍软件、后门程序、账单欺诈、短信欺诈、电…

超低延迟音视频直播技术的未来发展与创新

引言 音视频直播技术正在深刻改变着我们的生活和工作方式&#xff0c;尤其是在教育、医疗、安防、娱乐等行业。无论是全球性的体育赛事、远程医疗、在线教育&#xff0c;还是智慧安防、智能家居等应用场景&#xff0c;都离不开音视频技术的支持。为了应对越来越高的需求&#x…

系统架构设计(十二):统一过程模型(RUP)

简介 RUP 是由 IBM Rational 公司提出的一种 面向对象的软件工程过程模型&#xff0c;以 UML 为建模语言&#xff0c;是一种 以用例为驱动、以架构为中心、迭代式、增量开发的过程模型。 三大特征 特征说明以用例为驱动&#xff08;Use Case Driven&#xff09;需求分析和测…

海康相机连接测试-极简版

文章目录 1、下载客户端 1、下载客户端 海康机器人官网下载软件 软件下载地址 先下载客户端测试连接 按照你的相机的类型选择客户端 安装完毕后&#xff0c;确保USB线插的是3.0的端口 软件会自动识别相机型号 在上方有播放按钮&#xff0c;可以采集图像信息显示

Linux 磁盘扩容实战案例:从问题发现到完美解决

Linux 磁盘扩容实战案例&#xff1a;从问题发现到完美解决 案例背景 某企业服务器根目录 (/) 空间不足&#xff0c;运维人员通过 df -h 发现 /dev/vda1 分区已 100% 占满&#xff08;99G 已用&#xff09;。检查发现物理磁盘 /dev/vda 已扩展至 200G&#xff0c;但分区和文件…

深入解析FramePack:高效视频帧打包技术原理与实践

摘要 本文深入探讨FramePack技术在视频处理领域的核心原理&#xff0c;解析其在不同场景下的应用优势&#xff0c;并通过OpenCV代码示例演示具体实现方法&#xff0c;为开发者提供可落地的技术解决方案。 目录 1. FramePack技术背景 2. 核心工作原理剖析 3. 典型应用场景 …

RVTools 官网遭入侵,被用于分发携带 Bumblebee 恶意软件的篡改安装包

VMware 环境报告工具 RVTools 的官方网站遭黑客入侵&#xff0c;其安装程序被植入恶意代码。安全研究人员 Aidan Leon 发现&#xff0c;从该网站下载的受感染安装程序会侧加载一个恶意 DLL 文件&#xff0c;经确认是已知的 Bumblebee 恶意软件加载器。 官方回应与风险提示 RV…

mysql故障排查与环境优化

一、mysql运行原理 mysql的运行分为三层 客户端和连接服务 核心服务功能&#xff08;sql接口、缓存的查询、sql的分析和优化以及部分内置函数的执行等。&#xff09; 存储引擎层&#xff08;负责mysql中数据的存储和提取。&#xff09; 二、示例 1、实验环…

Codex与LangChain结合的智能代理架构:重塑软件开发的未来

🔥「炎码工坊」技术弹药已装填! 点击关注 → 解锁工业级干货【工具实测|项目避坑|源码燃烧指南】 引言:当代码生成遇见智能决策 想象以下场景: 凌晨三点:你需要紧急修复一个遗留系统的内存泄漏漏洞,但代码注释缺失且逻辑复杂; 产品经理需求变更:要求在24小时内将现有…

【开源Agent框架】CAMEL:角色扮演+任务分解

一、项目概览:重新定义智能体协作范式 CAMEL(Communicative Agents for “Mind” Exploration of Large Language Model Society)是由camel-ai社区开发的开源多智能体框架,致力于探索智能体的规模法则(Scaling Laws)。该项目通过构建包含百万级智能体的复杂社会系统,研…

第32节:基于ImageNet预训练模型的迁移学习与微调

1. 引言 在深度学习领域,迁移学习(Transfer Learning)已经成为解决计算机视觉任务的重要方法,特别是在数据量有限的情况下。其中,基于ImageNet数据集预训练的模型因其强大的特征提取能力而被广泛应用于各种视觉任务。本文将详细介绍迁移学习的概念、ImageNet预训练模型的特…

celery独立部署接入数据库配置

目录结构&#xff1a; config下配置&#xff1a; __init__: import os import sys sys.path.append(os.getcwd()) from celery import CeleryappCelery(celeryTester) # 创建一个Celery实例&#xff0c;名字自定义 app.config_from_object(config.celery_config) # 从celery_…

攻防世界-题目名称-文件包含

进入环境 看到 include()&#xff0c;想到文件包含&#xff0c;用php伪协议 /?filenamephp://filter/readconvert.base64-encode/resourceflag.php do not hack!猜测可能是黑名单检测的敏感字符 输入单个字符串/?filenamebase64 还是显示do not hack&#xff01; 构造payl…

MySQL高频面试八连问(附场景化解析)

文章目录 "为什么订单查询突然变慢了&#xff1f;"——从这个问题开始说起一、索引的生死时速&#xff08;必考题&#xff01;&#xff09;二、事务的"套娃"艺术三、锁机制的相爱相杀四、存储引擎的抉择五、慢查询的破案技巧六、分页的深度优化七、高可用架…

Android 中 自定义生成的 APK/AAR 文件名称

在 Kotlin DSL 中&#xff0c;可以通过配置 build.gradle.kts 文件来自定义生成的 APK 或 AAR 文件名称。 1、自定义 APK 名称 在模块的 build.gradle.kts 中通过修改 applicationVariants.all 配置来实现。 android {......applicationVariants.all {outputs.all {val df …

《从零开始:Spring Cloud Eureka 配置与服务注册全流程》​

关于Eureka的学习&#xff0c;主要学习如何搭建Eureka&#xff0c;将order-service和product-service都注册到Eureka。 1.为什么使用Eureka? 我在实现一个查询订单功能时&#xff0c;希望可以根据订单中productId去获取对应商品的详细信息&#xff0c;但是产品服务和订单服…