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

键盘聚焦a标签时如何为div.sub_menu添加display:block样式

键盘聚焦触发下拉子菜单显示实现方案

核心问题很明确:你已经获取到触发聚焦的<a>元素,对应的.sub_menu就是这个a标签所在li.dir的直接子元素,用原生DOM API可以直接精准定位,不需要复杂遍历。

实现思路

  • 精准定位子菜单:从绑定事件的<a>出发,先拿到父级li.dir节点,再查找这个li下的直接子级.sub_menu即可,不会误选其他嵌套层级的子菜单。
  • 优化类名操作:不要直接全量赋值className属性,用classListAPI做类名增删,避免覆盖元素上原有的类(比如示例里首页li自带的current类会被你原来的写法抹掉)。
  • 补全交互闭环:除了focus事件,还要绑定blur失焦事件,焦点离开菜单项时自动关闭子菜单,同步更新aria无障碍属性,符合键盘操作的交互逻辑。
  • 样式控制优先用类:比直接写行内style更易维护,如果你必须要加行内display:block样式,也可以在拿到sub_menu元素后直接修改style属性。

参考代码

首先加基础默认样式,保证子菜单初始是隐藏的:

/* 初始隐藏子菜单 */
.sub_menu {
  display: none;
}
/* 激活状态显示子菜单 */
li.dir.menu_hover .sub_menu {
  display: block;
}

修正后的JS逻辑:

const menuItems = document.querySelectorAll('li.dir');
menuItems.forEach(function(menuItem) {
  const trigger = menuItem.querySelector('a[aria-haspopup="true"]');
  // 定位当前li下的直接子级sub_menu,兼容后续DOM结构调整
  const subMenu = menuItem.querySelector(':scope > .sub_menu');

  // 聚焦显示逻辑
  trigger.addEventListener('focus', function(e) {
    menuItem.classList.add('menu_hover');
    trigger.setAttribute('aria-expanded', 'true');
    // 如果需要直接加行内样式,放开下面这行注释即可
    // subMenu.style.display = 'block';
    e.preventDefault();
  });

  // 失焦关闭逻辑
  trigger.addEventListener('blur', function(e) {
    menuItem.classList.remove('menu_hover');
    trigger.setAttribute('aria-expanded', 'false');
    // 对应行内样式写法放开下面注释
    // subMenu.style.display = 'none';
  });
});

关键注意点

用:scope > .sub_menu选择器的好处是,只要.sub_menu是li的直接子元素,不管你后续在a标签和sub_menu之间加什么其他元素(比如下拉箭头、装饰标签),选择逻辑都不会失效,比取nextElementSibling的容错率更高。

  • 如果你需要兼容非常老的不支持:scope的浏览器,直接把定位sub_menu的代码换成const subMenu = trigger.nextElementSibling;即可,对应你现在的DOM结构完全可以正常运行。
  • 原有逻辑里判断父节点className的分支完全没必要,因为你一开始选择的就是所有li.dir节点,父节点必然是dir类,不需要额外判断。
  • 绑定事件的时候不需要用Array.prototype.forEach.call转类数组,现代浏览器直接调用NodeList的forEach方法就可以跑。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.30 15:42:22