前端JavaScript-嵌套事件

news2025/5/23 22:47:35

点击

如果在多层嵌套中,对每层都设置事件监视器,试试看

<!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.coloradmin.cn/o/2384197.html

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

相关文章

X 下载器 2.1.42 | 国外媒体下载工具 网页视频嗅探下载

X 下载器让你能够轻松地从社交应用如Facebook、Instagram、TikTok等下载视频和图片。通过内置浏览器访问网站&#xff0c;它能自动检测视频和图片&#xff0c;只需点击下载按钮即可完成下载。去除广告&#xff0c;解锁本地会员&#xff0c;享受无广告打扰的下载体验。 大小&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 简介 为了有效地利用雾状冰生长的物理现象&#xff0c;最近开发了一种优化算法——雾状优化算法&#xff08;RIME&#xff09;。它模拟硬雾状和软雾状过程&#xff0c;构建硬雾状穿刺和软雾状搜索机制。在本研究中&#xff0c;引入了一种增强版本&#xff0c;称为修改的RIME…

服务器安装xfce桌面环境并通过浏览器操控

最近需要运行某个浏览器的脚本&#xff0c;但是服务器没有桌面环境&#xff0c;无法使用&#xff0c;遂找到了KasmVNC&#xff0c;并配合xfce实现低占用的桌面环境&#xff0c;可以直接使用浏览器进行操作 本文基于雨云——新一代云服务提供商的Debian11服务器操作&#xff0c;…

Oracle 创建外部表

找别人要一下数据&#xff0c;但是他发来一个 xxx.csv 文件&#xff0c;怎么办&#xff1f; 1、使用视图化工具导入 使用导入工具导入&#xff0c;如 DBeaver&#xff0c;右击要导入的表&#xff0c;选择导入数据。 选择对应的 csv 文件&#xff0c;下一步就行了&#xff08;如…

大语言模型 17 - MCP Model Context Protocol 介绍对比分析 基本环境配置

MCP 基本介绍 官方地址&#xff1a; https://modelcontextprotocol.io/introduction “MCP 是一种开放协议&#xff0c;旨在标准化应用程序向大型语言模型&#xff08;LLM&#xff09;提供上下文的方式。可以把 MCP 想象成 AI 应用程序的 USB-C 接口。就像 USB-C 提供了一种…

【软考向】Chapter 9 数据库技术基础

基本概念数据库的三级模式结构 数据模型E-R 模型关系模型各种键完整性约束 关系代数5 种基本的关系代数运算&#xff1a;并、差、笛卡儿积、投影和选择扩展的关系代数运算&#xff1a;交(Intersection)、连接(Join)、除(Division)、广义投影(Generalized Projection)、外连接(O…

实战:Dify智能体+Java=自动化运营工具!

我们在运营某个圈子的时候&#xff0c;可能每天都要将这个圈子的“热门新闻”发送到朋友圈或聊天群里&#xff0c;但依靠传统的实现手段非常耗时耗力&#xff0c;我们通常要先收集热门新闻&#xff0c;再组装要新闻内容&#xff0c;再根据内容设计海报等。 那怎么才能简化并高…

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简介 在嵌入式系统中&#xff0c;emWin、LVGL、TouchGFX 和 Qt 是…

应届本科生简历制作指南

一、找一个专业的简历模板 首先&#xff0c;你需要访问 Overleaf 的官方网站&#xff0c;也就是Overleaf, Online LaTeX Editor&#xff0c;进入页面后&#xff0c;点击注册按钮&#xff0c;按照提示填写相关信息来创建一个属于自己的账号&#xff0c;通常需要填写用户名、邮箱…

PyTorch可视化工具——使用Visdom进行深度学习可视化

文章目录 前置环境Visdom安装并启动VisdomVisdom图形APIVisdom静态更新API详解通用参数说明使用示例Visdom动态更新API详解1. 使用updateappend参数2. ~~使用vis.updateTrace方法~~3. 完整训练监控示例 Visdom可视化操作散点图plot.scatter()散点图案例线性图vis.line()vis.lin…

企业级爬虫进阶开发指南

企业级爬虫进阶开发指南 一、分布式任务调度系统的深度设计 1.1 架构设计原理 图表 1.2 核心代码实现与注释 分布式锁服务 # distributed_lock.py import redis import timeclass DistributedLock:def __init__(self, redis_conn):self.redis = redis_connself.lock_key = …

网络安全-等级保护(等保) 2-7 GB/T 25058—2019 《信息安全技术 网络安全等级保护实施指南》-2019-08-30发布【现行】

################################################################################ GB/T 22239-2019 《信息安全技术 网络安全等级保护基础要求》包含安全物理环境、安全通信网络、安全区域边界、安全计算环境、安全管理中心、安全管理制度、安全管理机构、安全管理人员、安…

数据结构实验10.1:内部排序的基本运算

文章目录 一&#xff0c;实验目的二&#xff0c;实验内容1. 数据生成与初始化2. 排序算法实现&#xff08;1&#xff09;直接插入排序&#xff08;2&#xff09;二分插入排序&#xff08;3&#xff09;希尔排序&#xff08;4&#xff09;冒泡排序&#xff08;5&#xff09;快速…

wps编辑技巧

1、编辑模式 2、图片提取方法&#xff1a;右键保存图片 可以直接右键保存下来看看是否是原始图&#xff0c;如果歪着的图&#xff0c;可能保存下来是正的&#xff0c;直接保存试下 3、加批注

开放世界RPG:无缝地图与动态任务的拓扑学架构

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

【图像处理入门】1. 数字图像的本质:从像素到色彩模型

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

(已解决:基于WSL2技术)Windows11家庭中文版(win11家庭版)如何配置和使用Docker Desktop

目录 问题现象&#xff1a; 问题分析&#xff1a; 拓展&#xff1a; 解决方法&#xff1a; 1、使用WSL2技术&#xff08;亲测有效&#xff09; 注意&#xff1a; 2、开启Hyper-V功能&#xff08;未经亲测&#xff0c;待研究&#xff09; 问题现象&#xff1a; 今天想在本…

Ubuntu20.04部署KVM

文章目录 一. 环境准备关闭防火墙&#xff08;UFW&#xff09;禁用 SELinux更换镜像源检查 CPU 虚拟化支持 二. 安装KVM安装 KVM 及相关组件启动 libvirtd 服务验证安装创建虚拟机 一. 环境准备 4C8G&#xff0c;50G硬盘——VMware Workstation需要给虚拟机开启虚拟化引擎 roo…

OpenCV CUDA 模块图像过滤------创建一个高斯滤波器函数createGaussianFilter()

操作系统&#xff1a;ubuntu22.04 OpenCV版本&#xff1a;OpenCV4.9 IDE:Visual Studio Code 编程语言&#xff1a;C11 算法描述 cv::cuda::createGaussianFilter 是 OpenCV CUDA 模块中的一个工厂函数&#xff0c;用于创建一个高斯滤波器。这个滤波器可以用来平滑图像&#…