You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

点击用户头像名称时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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.23 12:24:20