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

站点导航可访问性问题:回车键无法打开子导航,空格键触发后子导航闪灭

问题根因
  • 事件绑定层级错误:你将click和keypress事件绑定在了父级li元素上,而非作为交互触发器的button元素。当聚焦在button上按下空格/回车时,button自带的默认点击行为会触发一次冒泡到li的click事件,加上你绑定在li上的keypress事件会先触发一次,导致toggleItem连续执行两次,子菜单刚被打开就被关闭,表现为闪现。
  • keypress事件已被废弃,不同浏览器对回车、空格的触发逻辑存在兼容性差异,是回车无响应的核心原因之一。
  • 属性绑定逻辑错误:aria-expanded是可交互触发元素(button)的属性,你当前将属性设置到了li元素上,且状态值写反:新增submenu-active激活状态时,aria-expanded应设为true,你的代码里设为了false。
  • 变量未定义:代码中直接使用的site_menu没有提前声明赋值,会触发JS报错,打断逻辑执行。
优化方案
  1. 调整事件绑定对象:将事件直接绑定到子菜单触发button上,避免重复触发问题
  2. 替换keypress为标准的keydown事件,仅监听回车、空格两个触发键,同时阻止默认行为避免重复触发
  3. 修正toggleItem的状态逻辑,正确设置aria-expanded属性
  4. 补充缺失的site_menu变量声明
  5. 优化关闭逻辑,ESC关闭后将焦点返回触发按钮,符合可访问性规范

以下是修正后的完整JS代码:

// 补充缺失的site_menu声明
const site_menu = document.querySelector(".site-menu");
const items = document.querySelectorAll(".site-menu__item--has-submenu");
const subButtons = document.querySelectorAll(".site-menu__item--has-submenu button");

// 激活子菜单
function toggleItem(e) {
  // 键盘事件仅响应回车和空格
  if (e.type === 'keydown' && !['Enter', ' '].includes(e.key)) {
    return;
  }
  // 阻止默认行为,避免button自带点击事件重复触发
  e.preventDefault();
  e.stopPropagation();
  // 获取当前触发按钮对应的父级li
  const parentItem = this.closest('.site-menu__item--has-submenu');
  const isActive = parentItem.classList.contains("submenu-active");
  
  // 先关闭所有已激活的子菜单
  site_menu.querySelectorAll(".submenu-active").forEach(active => {
    active.classList.remove("submenu-active");
    active.querySelector('button').setAttribute('aria-expanded', 'false');
  });

  // 切换当前菜单状态
  if (!isActive) {
    parentItem.classList.add("submenu-active");
    this.setAttribute('aria-expanded', 'true');
  } else {
    this.setAttribute('aria-expanded', 'false');
  }
}

// 事件绑定到button上
subButtons.forEach(btn => {
  btn.addEventListener("click", toggleItem, false);
  btn.addEventListener("keydown", toggleItem, false);
});

// 点击任意位置关闭子菜单
function closeSubmenu(e) {
  const isClickInside = site_menu.contains(e.target);
  if (!isClickInside && site_menu.querySelector(".submenu-active")) {
    const activeItem = site_menu.querySelector(".submenu-active");
    activeItem.classList.remove("submenu-active");
    activeItem.querySelector('button').setAttribute('aria-expanded', 'false');
  }
}

document.addEventListener("click", closeSubmenu, false);
document.addEventListener('keydown', (event) => {
  if (event.key === 'Escape' && !(event.ctrlKey || event.altKey || event.shiftKey)) {
    const activeItem = site_menu.querySelector(".submenu-active");
    if (activeItem) {
      activeItem.classList.remove("submenu-active");
      const triggerBtn = activeItem.querySelector('button');
      triggerBtn.setAttribute('aria-expanded', 'false');
      // 焦点返回触发按钮,符合可访问性要求
      triggerBtn.focus();
    }
  }
});

内容的提问来源于stack exchange,提问作者xoam

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.01 16:36:04