点击用户头像名称时Dropdown菜单不显示,设aria-expanded=true才显示求助
问题排查:Dropdown菜单点击无法触发显示
配置了Dropdown菜单,预期点击用户头像名称时菜单弹出,但目前无法正常触发。只有手动为菜单添加aria-expanded="true"属性时,菜单才会显示。
现有代码
HBS代码
{{#if signed_in}} <div class="user-info dropdown" > <button class="dropdown_toggle" aria-haspopup="true"> {{user_avatar class="user-avatar"}} {{user_name}} <span> <svg xmlns="IMAGELINK" width="12" height="12" focusable="false" viewBox="0 0 12 12" class="dropdown-chevron-icon" aria-hidden="true"> <path fill="none" stroke="currentColor" stroke-linecap="round" d="M3 4.5l2.6 2.6c.2.2.5.2.7 0L9 4.5"/> </svg> </span> </button> <div class="dropdown-menu" role="menu" aria-expanded="true"> {{#my_profile role="menuitem"}}{{t 'profile'}}{{/my_profile}} {{link "requests" role="menuitem"}} <div class="separator" role="separator"></div> {{link "sign_out" role="menuitem"}} </div> </div> {{/if}}
脚本代码
// Dropdowns function Dropdown(toggle, menu) { this.toggle = toggle; this.menu = menu; this.menuPlacement = { top: menu.classList.contains("dropdown-menu-top"), end: menu.classList.contains("dropdown-menu-end") }; this.toggle.addEventListener("click", this.clickHandler.bind(this)); this.toggle.addEventListener("keydown", this.toggleKeyHandler.bind(this)); this.menu.addEventListener("keydown", this.menuKeyHandler.bind(this)); }
CSS代码
.dropdown-menu { background: #fff; border: 1px solid #d8d8d8; border-radius: 3px; box-shadow: 0 1px 5px rgba(0, 0, 0, 0.1); display: none; font-size: 14px; font-style: normal; font-weight: normal; left: 0; margin-top: 1px; min-width: 170px; padding: 10px 0; position: absolute; text-align: left; z-index: 1000; } [dir="rtl"] .dropdown-menu { text-align: right; } .dropdown-menu[aria-expanded="true"] { display: block; }
解决步骤
1. 补全Dropdown类的事件处理函数
当前脚本仅添加了事件监听,但核心的clickHandler等方法未实现,导致点击时没有逻辑切换菜单状态。需补充以下代码:
function Dropdown(toggle, menu) { this.toggle = toggle; this.menu = menu; this.menuPlacement = { top: menu.classList.contains("dropdown-menu-top"), end: menu.classList.contains("dropdown-menu-end") }; // 初始化aria属性:默认隐藏状态 this.toggle.setAttribute('aria-expanded', 'false'); this.menu.setAttribute('aria-expanded', 'false'); this.toggle.addEventListener("click", this.clickHandler.bind(this)); this.toggle.addEventListener("keydown", this.toggleKeyHandler.bind(this)); this.menu.addEventListener("keydown", this.menuKeyHandler.bind(this)); } // 点击切换菜单显示/隐藏 Dropdown.prototype.clickHandler = function() { const isExpanded = this.menu.getAttribute('aria-expanded') === 'true'; const newState = !isExpanded; this.menu.setAttribute('aria-expanded', newState.toString()); this.toggle.setAttribute('aria-expanded', newState.toString()); }; // 键盘控制(增强 accessibility) Dropdown.prototype.toggleKeyHandler = function(e) { switch(e.key) { case 'Enter': case ' ': e.preventDefault(); this.clickHandler(); break; case 'ArrowDown': e.preventDefault(); this.clickHandler(); this.menu.querySelector('[role="menuitem"]')?.focus(); break; } }; Dropdown.prototype.menuKeyHandler = function(e) { const items = Array.from(this.menu.querySelectorAll('[role="menuitem"]')); const currentIndex = items.indexOf(document.activeElement); switch(e.key) { case 'ArrowUp': e.preventDefault(); const prevItem = items[currentIndex - 1] || items[items.length - 1]; prevItem.focus(); break; case 'ArrowDown': e.preventDefault(); const nextItem = items[currentIndex + 1] || items[0]; nextItem.focus(); break; case 'Escape': e.preventDefault(); this.clickHandler(); this.toggle.focus(); break; } };
2. 修正HBS初始属性
当前HBS中.dropdown-menu默认设置aria-expanded="true",会导致页面加载时菜单默认显示,需改为false:
<div class="dropdown-menu" role="menu" aria-expanded="false">
3. 初始化Dropdown实例
页面加载完成后,需找到对应元素并实例化Dropdown:
document.addEventListener('DOMContentLoaded', function() { const dropdownContainers = document.querySelectorAll('.dropdown'); dropdownContainers.forEach(container => { const toggle = container.querySelector('.dropdown_toggle'); const menu = container.querySelector('.dropdown-menu'); if (toggle && menu) { new Dropdown(toggle, menu); } }); });
4. CSS逻辑无需修改
当前CSS通过.dropdown-menu[aria-expanded="true"]控制显示,逻辑匹配需求,保持原样即可。
内容的提问来源于stack exchange,提问作者Noelle
相关产品推荐
相关产品推荐

