
在现代web应用中,下拉菜单(dropdown menu)是常见的ui组件,通常通过点击一个触发按钮来打开或关闭。然而,一个良好的用户体验要求下拉菜单不仅可以通过再次点击触发按钮关闭,更应该在用户点击页面上的任何其他非菜单区域时自动关闭。
传统的实现方式可能只关注按钮点击事件,导致菜单打开后,用户必须精确地点击原始按钮才能将其关闭。当尝试通过监听document.body的点击事件来实现外部关闭时,开发者常会遇到判断逻辑上的困难,例如如何区分点击发生在菜单内部、触发按钮上还是页面其他区域。如果处理不当,可能会导致菜单在打开后立即关闭,或者点击菜单内部元素时菜单也意外关闭。
核心挑战在于精确地识别点击事件的目标元素(event.target)与菜单及触发按钮之间的关系。我们需要一种机制,能够判断event.target是否是菜单元素或其子元素,以及是否是触发按钮或其子元素。
解决上述问题的关键在于利用JavaScript的事件委托机制和Element.closest()方法。
事件委托 (document 事件监听) 将点击事件监听器附加到document对象上,而不是document.body。这是因为document是所有DOM元素的根节点,可以捕获到页面上任何元素的点击事件,无论该元素是否直接位于body内。当点击事件发生时,它会从实际被点击的元素向上冒泡,直到document,此时我们可以统一处理。
event.target.closest() 方法Element.closest(selector)方法是判断点击事件目标元素与特定父元素关系的关键。它会遍历当前元素及其父元素(包括自身),直到找到一个与指定CSS选择器匹配的祖先元素。如果找到,则返回该祖先元素;如果遍历到文档根节点仍未找到,则返回null。
利用这一特性,我们可以:
结合这两个判断,我们就能精确地识别出“点击既不在菜单内部也不在触发按钮内部”的情况,从而安全地关闭菜单。
下面我们将结合HTML、CSS和JavaScript来演示如何实现这一功能。
我们的HTML结构包含一个触发按钮和一个下拉菜单容器。
<button class="user_menu_button">
<i class="icn_button fa-solid fa-bars"></i>
<span class="txt_button">Account</span>
</button>
<div class="mts_menu_container">
<div class="dropdown_box">
<div id="mts_menu" class="mts_dropdown_content">
<div class="user_menu header">
<span class="display name">Ciao [display_name]</span>
<span class="display mail">[display_email]</span>
</div>
<hr class="divider-menu">
<div class="mnu_margin">
<div class="user_menu item">
<a href="/account">
<i class="icn_menu fa-regular fa-user"></i>
<span class="link_text">Dashboard</span>
</a>
</div>
<div class="user_menu item">
<a href="ordini">
<i class="icn_menu fa-regular fa-basket-shopping"></i>
<span class="link_text">I miei ordini</span>
</a>
</div>
<div class="user_menu item">
<a href="libreria">
<i class="icn_menu fa-regular fa-cloud-arrow-down"></i>
<span class="link_text">Downloads</span>
</a>
</div>
<div class="user_menu item">
<a href="impostazioni">
<i class="icn_menu fa-regular fa-gear"></i>
<span class="link_text">Impostazioni</span>
</a>
</div>
<div class="user_menu item last">
<a href="wp-login.php?action=logout">
<i class="icn_menu fa-regular fa-arrow-right-from-bracket"></i>
<span class="link_text">Logout</span>
</a>
</div>
</div>
</div>
</div>
</div>关键元素:
CSS主要负责菜单的初始隐藏状态和显示时的样式。.mts_dropdown_content 定义了菜单的默认样式,而 .mts_dropdown_content.show 类则控制菜单的可见性、高度和动画效果。
/*Button Toggle Menu*/
.user_menu_button {
display: flex;
align-content: center;
justify-content: center;
align-items: center;
width: 100%;
height: 32px;
background: #3D4350!important;
border-radius: 4px;
padding: 12px;
font-size: 14px!important;
line-height: 2;
}
.icn_button {
margin: 0;
}
.icn_button:before, .icn_button:after {
margin: 0;
}
.txt_button {
margin-left: 10px;
color: #fff;
font-size: 14px;
font-weight: 400;
}
/*Items menu*/
.user_menu {
display: flex;
flex-direction: column;
}
.user_menu.header {
padding: 15px 15px;
}
/*Menu header info*/
.display.name {
font-size: 14px;
font-weight: 500;
color: #303238;
line-height: 1.5;
}
.display.mail {
font-size: 13px;
color: #1E70EB;
line-height: 1.5;
}
hr.divider-menu {
border-top: 1px solid #e0e0e0;
}
/*Text Link css*/
.mnu_margin {
margin: 7px 0;
}
.user_menu.item > a {
display: flex;
justify-content: flex-start;
align-items: center;
padding: 8px 15px;
color: #212629;
}
.user_menu.item:hover > a {
color: #fff;
background: #1E70EB;
transition: all 0.2s;
}
.user_menu.item > a .link_text {
font-size: 14px;
color: #212629;
}
.user_menu.item:hover > a .link_text {
color: #fff;
}
/*Icon Items Menu*/
.icn_menu:before, .icon_menu:after {
margin: 0px;
padding: 0px;
font-size: 16px
}
.icn_menu {
margin-right: 10px;
display: flex !important;
align-items: center;
justify-content: center;
width: 22px;
height: 22px;
}
/* User Menu For header website */以上就是实现点击页面任意位置关闭下拉菜单的详细内容,更多请关注php中文网其它相关文章!
每个人都需要一台速度更快、更稳定的 PC。随着时间的推移,垃圾文件、旧注册表数据和不必要的后台进程会占用资源并降低性能。幸运的是,许多工具可以让 Windows 保持平稳运行。
Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号