You need to enable JavaScript to run this app. Accordion组件键盘导航开发:如何实现上下箭头切换相邻面板功能
优惠活动
大模型
产品
解决方案
定价
更多

Accordion组件键盘导航开发:如何实现上下箭头切换相邻面板功能

手风琴组件方向键导航实现方案

实现思路

现有代码只实现了点击切换、Enter/Space触发的基础能力,要支持上下方向键导航,只需要补全两块逻辑:

  • 给每个手风琴标题内的触发按钮绑定keydown监听,识别上下方向键的按下动作
  • 按按钮的排列顺序计算相邻位置,直接将焦点移动到相邻按钮上,省去用户按Tab跳转的步骤

容易踩的实现坑

  • 方向键这类功能键无法被keypress事件捕获,必须用keydown做监听
  • 方向键按下时一定要调用preventDefault(),不然会触发浏览器默认的页面上下滚动,破坏交互体验
  • 可以提前把所有触发按钮整理成有序数组,不用每次按键都重新查询DOM,减少不必要的DOM操作开销

可直接复用的改造代码

(function () {
  const headings = document.querySelectorAll(".unr-accordion--heading");
  // 按DOM顺序整理所有手风琴触发按钮,方便直接按索引取相邻元素
  const accordionButtons = Array.from(headings).map(heading => heading.querySelector("button"));

  accordionButtons.forEach((btn, currentIndex) => {
    // 获取当前按钮关联的折叠面板,逻辑和原有代码保持一致
    const targetPanel = btn.parentElement.nextElementSibling;

    // 保留原有点击切换展开/折叠的逻辑
    btn.onclick = () => {
      const isExpanded = btn.getAttribute("aria-expanded") === "true";
      btn.setAttribute("aria-expanded", !isExpanded);
      targetPanel.hidden = isExpanded;
    };

    // 新增方向键导航的键盘事件
    btn.addEventListener("keydown", (e) => {
      // 只处理上下方向键,不干扰其他按键的原有行为
      if (e.key !== "ArrowUp" && e.key !== "ArrowDown") return;
      // 阻止方向键默认触发的页面滚动
      e.preventDefault();

      let targetBtnIndex;
      if (e.key === "ArrowUp") {
        // 上键导航:默认做首尾循环,如果不需要循环,此处到达第一个按钮时直接return即可
        targetBtnIndex = currentIndex === 0 ? accordionButtons.length - 1 : currentIndex - 1;
      } else {
        // 下键导航:默认做首尾循环,如果不需要循环,此处到达最后一个按钮时直接return即可
        targetBtnIndex = currentIndex === accordionButtons.length - 1 ? 0 : currentIndex + 1;
      }

      // 把焦点直接移动到目标按钮,完成相邻面板的导航
      accordionButtons[targetBtnIndex].focus();
    });
  });
})();

适配动态场景的调整

如果你的手风琴面板是动态加载/卸载的,不要在初始化阶段固定存储按钮数组,每次方向键触发时再实时查询当前页面上的所有手风琴触发按钮计算相邻索引,避免拿到已经被DOM移除的失效元素。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.23 16:45:09