2023.12.3使用原生js实现进阶版手风琴菜单(前端冒泡事件处理)
之前写了一个基础版,现在这个是完全版,补充实现点击空白区域菜单折叠、点击某一菜单其余菜单折叠的功能,该写法可以用于整个网页所有下拉菜单的实现,并且可以结合css灵活进行样式调整。
之前基础版的代码见:2023.12.1 手风琴菜单的简便实现方式
https://editor.csdn.net/md/?articleId=134759727
关注事件冒泡的处理
在早期编写的过程中,未考虑事件冒泡的影响,因此特效时常会出现不稳定执行的情况,检查代码后,怀疑是事件冒泡导致,事件冒泡是指当一个元素上的事件被触发时,它会向父级元素传递,直到传递到文档根节点为止。这意味着如果在子元素上点击某个事件,该事件会依次传递到父元素,所有祖先元素,直到文档根节点。这可能会导致不必要的副作用或影响,特别是当有多个嵌套的元素并且希望在其中一个元素上执行特定操作时。
因此,为了防止事件传递到其他元素,使用 stopPropagation() 方法来阻止事件冒泡。这将防止事件传递到其他元素,仅在当前元素上执行操作。
在每个子菜单上都添加了一个点击事件监听器,用于阻止事件继续传递给其父元素。这确保了只有在子菜单上点击时,才会执行相应的操作,而不会触发父菜单的点击事件。
最后执行效果满意。
附源代码:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>后端管理网站</title>
<style>
/* 隐藏下拉菜单 */
.submenu {
display: none;
}
</style>
</head>
<body>
<ul>
<li><a href="#">首页</a></li>
<li><a href="#" onclick="toggleMenu(event, 'menu1')">菜单1</a>
<ul id="menu1" class="submenu">
<li><a href="#">子菜单1</a></li>
<li><a href="#">子菜单2</a></li>
<li><a href="#">子菜单3</a></li>
</ul>
</li>
<li><a href="#" onclick="toggleMenu(event, 'menu2')">菜单2</a>
<ul id="menu2" class="submenu">
<li><a href="#">子菜单4</a></li>
<li><a href="#">子菜单5</a></li>
<li><a href="#">子菜单6</a></li>
</ul>
</li>
<li><a href="#">菜单3</a></li>
</ul>
<script>
// 获取所有带有 "submenu" 类的元素
var submenus = document.getElementsByClassName("submenu");
// 为所有子菜单添加点击事件监听器
for (var i = 0; i < submenus.length; i++) {
submenus[i].addEventListener("click", function(event) {
event.stopPropagation(); // 阻止事件冒泡
});
}
// 点击菜单时切换菜单的显示状态
function toggleMenu(event, id) {
var menu = document.getElementById(id);
if (menu.style.display === 'block') {
menu.style.display = 'none';
} else {
closeAllMenus();
menu.style.display = 'block';
}
event.stopPropagation(); // 阻止事件冒泡
}
// 关闭所有菜单
function closeAllMenus() {
for (var i = 0; i < submenus.length; i++) {
submenus[i].style.display = 'none';
}
}
// 在页面点击时关闭所有菜单
document.addEventListener("click", function() {
closeAllMenus();
});
</script>
</body>
</html>