当前位置: 首页 > news >正文

記錄js中的冒泡事件

https://chat.deepseek.com/share/0uyt5lgfv5jrac6frn

该对话来自分享,由 AI 生成,请仔细甄别。

<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Document</title> <link href="../bootstrap-5.3.8/dist/css/bootstrap.css" rel="stylesheet" /> <link href="../icons-1.13.1/font/bootstrap-icons.css" rel="stylesheet" /> <link href="./my_menu_test.css" rel="stylesheet" /> </head> <body> <div class="body-content"> <!-- 菜單 --> <div class="menu-wrapper"> <div class="menu-content"> <ul> <li class="menu-item active" data-menu-type="ctlmenu"> <a href="#"> <i class="bi bi-file-earmark-spreadsheet"></i> <p>菜單001</p> <i class="bi bi-chevron-left right-icon"></i> </a> <ul> <li class="menu-item" data-menu-type="action"> <a href=""> <i class="bi bi-file-earmark-spreadsheet"></i> <p>菜單00111</p> <i class="bi bi-chevron-left right-icon"></i> </a> </li> <li class="menu-item" data-menu-type="action"> <a href=""> <i class="bi bi-file-earmark-spreadsheet"></i> <p>菜單00112</p> <i class="bi bi-chevron-left right-icon"></i> </a> </li> <li class="menu-item" data-menu-type="action"> <a href=""> <i class="bi bi-file-earmark-spreadsheet"></i> <p>菜單00113</p> <i class="bi bi-chevron-left right-icon"></i> </a> </li> </ul> </li> <li class="menu-item" data-menu-type="ctlmenu"> <a href="#"> <i class="bi bi-file-earmark-spreadsheet"></i> <p>菜單002</p> <i class="bi bi-chevron-left right-icon"></i> </a> <ul> <li class="menu-item"> <a href=""> <i class="bi bi-file-earmark-spreadsheet"></i> <p>菜單003</p> <i class="bi bi-chevron-left right-icon"></i> </a> </li> <li class="menu-item"> <a href=""> <i class="bi bi-file-earmark-spreadsheet"></i> <p>菜單004</p> <i class="bi bi-chevron-left right-icon"></i> </a> </li> <li class="menu-item"> <a href=""> <i class="bi bi-file-earmark-spreadsheet"></i> <p>菜單005</p> <i class="bi bi-chevron-left right-icon"></i> </a> </li> </ul> </li> <li class="menu-item" data-menu-type="ctlmenu"> <a href="#"> <i class="bi bi-file-earmark-spreadsheet"></i> <p>菜單006</p> <i class="bi bi-chevron-left right-icon"></i> </a> <ul> <li class="menu-item" data-menu-type="action"> <a href=""> <i class="bi bi-file-earmark-spreadsheet"></i> <p>菜單007</p> <i class="bi bi-chevron-left right-icon"></i> </a> </li> <li class="menu-item" data-menu-type="action"> <a href=""> <i class="bi bi-file-earmark-spreadsheet"></i> <p>菜單008</p> <i class="bi bi-chevron-left right-icon"></i> </a> </li> <li class="menu-item" data-menu-type="ctlmenu"> <a href=""> <i class="bi bi-file-earmark-spreadsheet"></i> <p>菜單009</p> <i class="bi bi-chevron-left right-icon"></i> </a> <ul> <li class="menu-item"> <a href=""> <i class="bi bi-file-earmark-spreadsheet"></i> <p>菜單010</p> <i class="bi bi-chevron-left right-icon"></i> </a> </li> <li class="menu-item"> <a href=""> <i class="bi bi-file-earmark-spreadsheet"></i> <p>菜單011</p> <i class="bi bi-chevron-left right-icon"></i> </a> </li> <li class="menu-item"> <a href=""> <i class="bi bi-file-earmark-spreadsheet"></i> <p>菜單012</p> <i class="bi bi-chevron-left right-icon"></i> </a> </li> </ul> </li> </ul> </li> <li class="menu-item"> <a href="#"> <i class="bi bi-file-earmark-spreadsheet"></i> <p>菜單013</p> <i class="bi bi-chevron-left right-icon"></i> </a> </li> <li class="menu-item"> <a href="#"> <i class="bi bi-file-earmark-spreadsheet"></i> <p>菜單014</p> <i class="bi bi-chevron-left right-icon"></i> </a> </li> </ul> </div> </div> <!-- 右側內容區 --> <div class="main-content"> <!-- 內容區頭部 --> <div class="content-header"> <a href="#" class="user-info">用戶信息</a> </div> <!-- 內容區中間部分 --> <div class="content-body"> <div class="tab-headers"> <ul class="tab-list"> <li class="tab-item"> <a href="javascript:void(0)">tab1</a> <span class="tab-close">&times;</span> </li> <li class="tab-item"> <a href="javascript:void(0)">tab1111111111111111111111</a> <span class="tab-close">&times;</span> </li> <li class="tab-item"> <a href="javascript:void(0)">tab1</a> <span class="tab-close">&times;</span> </li> </ul> </div> <div class="tab-content"> tab-內容區中間部分 </div> </div> <!-- 內容區 底部 --> <div class="content-footer"> Copyright@foxconn.com 2025 </div> </div> </div> <script type="script" src="../bootstrap-5.3.8/dist/js/bootstrap.bundle.js"></script> <script> document.addEventListener('DOMContentLoaded',AddMenuItemClickEvent); // 所有的菜單li添加點擊事件 function AddMenuItemClickEvent(){ const ctlMenus=document.querySelectorAll('.menu-item'); ctlMenus.forEach(menuItem=>{ menuItem.addEventListener('click',(event)=>{ event.preventDefault(); // 检查点击的是否是当前菜单项的直接子链接 const clickMenu = event.target.closest('[data-menu-type]'); const menuType = clickMenu.dataset.menuType; alert(menuType); // if(clickedLink && clickedLink === menuItem) { // event.preventDefault(); // menuItem.classList.toggle("active"); // event.stopPropagation(); // 阻止事件继续冒泡 // } }) }) } </script> </body> </html> 請分析這段代碼,只分析我代碼出現的原因,不要重新去寫代碼 為什麼我點擊 “菜單00111” 會彈出2次action

分析你的代码,点击"菜單00111"弹出2次 action 的原因如下:

问题根源:事件冒泡 + 错误的选择器

1. 事件绑定问题

javascript

const ctlMenus=document.querySelectorAll('.menu-item');

这行代码选择了所有的 .menu-item 元素,包括:

  • 父级菜单项(如"菜單001")

  • 子级菜单项(如"菜單00111")

2. DOM 结构分析

当你点击"菜單00111"时,HTML结构是:

html

<li class="menu-item active" data-menu-type="ctlmenu"> <!-- 父级 --><a href="#">菜單001</a><ul><li class="menu-item" data-menu-type="action"> <!-- 子级 --><a href="">菜單00111</a></li></ul>
</li>

3. 事件触发流程

  1. 第一次触发:点击"菜單00111"时,事件冒泡到其父元素 <li class="menu-item" data-menu-type="action">

  2. 第二次触发:事件继续冒泡到祖父元素 <li class="menu-item active" data-menu-type="ctlmenu">

4. 关键问题代码

javascript

const clickMenu = event.target.closest('[data-menu-type]');
  • 第一次:找到 data-menu-type="action"(正确的)

  • 第二次:找到 data-menu-type="ctlmenu"(父级的)

总结

因为事件绑定到了所有层级的 .menu-item,且事件冒泡导致点击一个子菜单项时,会同时触发其所有父级菜单项的点击事件,所以会弹出2次警告框。

找到父級的時候,為什麼彈出的不是ctlmenu,而是兩次都是相同的信息“action”

你提出了一个很好的观察点。让我重新分析这个问题:

关键问题在于 event.target.closest() 的使用

代码逻辑分析:

javascript

const clickMenu = event.target.closest('[data-menu-type]');
const menuType = clickMenu.dataset.menuType;
alert(menuType);

实际点击时的DOM路径:

text

<li data-menu-type="ctlmenu"> (祖父级)↳ <li data-menu-type="action"> (父级) ← 事件绑定在这里↳ <a>菜單00111</a> ← 实际点击位置

两次触发时的 event.target 不同:

第一次触发(直接点击子菜单项时):

  • event.target = <a>菜單00111</a>(实际点击的链接)

  • event.target.closest('[data-menu-type]') 向上查找

  • 找到:<li data-menu-type="action">(父级)

  • 弹出:"action"

第二次触发(事件冒泡到祖父级时):

  • event.target 仍然 = <a>菜單00111</a>(事件源不变)

  • event.target.closest('[data-menu-type]') 再次向上查找

  • 找到:仍然是 <li data-menu-type="action">(因为从同一个事件源向上查找)

  • 弹出:"action"

为什么不是 "ctlmenu"

因为 event.target 在整个事件冒泡过程中保持不变,始终指向最初被点击的元素(<a>菜單00111</a>)。closest() 方法从当前元素向上查找,所以两次都找到同一个最近的 data-menu-type 元素。

正确的应该是:

javascript

// 应该使用 event.currentTarget 而不是 event.target.closest()
const menuType = event.currentTarget.dataset.menuType;

总结:你看到两次 "action" 是因为 event.target 在冒泡过程中保持不变,而 closest() 每次都从同一个起点向上查找,找到的是同一个最近的 data-menu-type 元素。

http://www.dtcms.com/a/526292.html

相关文章:

  • 腾讯云 怎样建设网站域客式单页网站能申请域名吗
  • 西双版纳州住房和城乡建设局网站wordpress注册美化
  • 多种方法找回Root密码详细操作步骤
  • 阿里云服务器建设网站视频网站用什么做的好
  • 大专生工作后还能专升本吗?对职业发展有帮助吗?
  • 棉桃剥壳机做网站重庆网站推广营销
  • 大学生简历免费制作网站互联网备案服务平台
  • 哪些网站用django做的狼雨seo网站排名查询
  • 网站制作公司推荐深圳黑马品牌网站设计
  • 做网站需要字体切换从用户旅程角度做网站分析
  • 橙色主题手机网站希爱力副作用太强了
  • 数字化转型:概念性名词浅谈(第八十讲)
  • 公司注册网站模板长沙口碑好网站建设企业
  • leetcode学习笔记3:轮转数组(多次翻转数组思想)
  • 新手网站建设教程图书宁波企业建站程序
  • 银川做网站建设wordpress多条件过滤
  • 【shell】每日shell练习:系统备份文件管理/系统性能趋势分析
  • 重庆门户网站开发报价app开发公司十强
  • 广东建设协会网站首页关键词推广seo
  • Orleans 配置方式时序图
  • 网站建设 空间杭州 电子商务网站建设 网络服务
  • 有哪些图片设计网站有哪些问题网站权重最高
  • 怎样上传网站到百度wordpress 文章截取
  • 网站建设120wordpress左右
  • 如何上传网站模板如何评价一个网站设计的好坏
  • 苏州做网站费用东莞模板建站平台
  • 个人资质网站做推广wordpress漏洞 2014
  • 小型企业网站建设项目网站整合方案
  • 波音网站开发四川省住房建设厅官网
  • 丰城网站建设厦门专业网站营销