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

如何为Bootstrap 5下拉菜单添加快捷键激活功能

Bootstrap 5下拉菜单快捷键激活实现方案

我们需要给Bootstrap 5的下拉菜单添加快捷键功能:当下拉菜单展开时,按下菜单项下划线标记的对应按键(如A、n、s、e),触发对应菜单项的点击事件,同时保留已实现的左右箭头切换下拉菜单的功能。

完整代码示例

HTML结构

<div class="btn-group">
  <button type="button" class="btn btn-danger dropdown-toggle" data-bs-toggle="dropdown" aria-expanded="false">
    Action
  </button>
  <ul class="dropdown-menu">
    <li><a class="dropdown-item" href="#"><u>A</u>ction</a></li>
    <li><a class="dropdown-item" href="#">A<u>n</u>other action</a></li>
    <li><a class="dropdown-item" href="#"><u>S</u>omething else here</a></li>
    <li><hr class="dropdown-divider"></li>
    <li><a class="dropdown-item" href="#">S<u>e</u>parated link</a></li>
  </ul>
</div>

JavaScript逻辑

document.addEventListener("DOMContentLoaded", function () {
    // 辅助函数:获取下一个同类型兄弟元素
    function getNextSibling(el, selector) {
        let next = el.nextElementSibling;
        while (next) {
            if (next.matches(selector)) return next;
            next = next.nextElementSibling;
        }
        return null;
    }

    // 辅助函数:获取上一个同类型兄弟元素
    function getPrevSibling(el, selector) {
        let prev = el.previousElementSibling;
        while (prev) {
            if (prev.matches(selector)) return prev;
            prev = prev.previousElementSibling;
        }
        return null;
    }

    document.querySelectorAll('.dropdown').forEach(function (dropdownEl) {
        dropdownEl.addEventListener('shown.bs.dropdown', function () {
            // 获取当前下拉菜单的所有菜单项
            const menuItems = dropdownEl.querySelectorAll('.dropdown-item');
            // 构建快捷键到菜单项的映射(不区分大小写)
            const hotkeyMap = new Map();
            menuItems.forEach(item => {
                const underlineEl = item.querySelector('u');
                if (underlineEl) {
                    const key = underlineEl.textContent.trim().toLowerCase();
                    hotkeyMap.set(key, item);
                }
            });

            function handleKeydown(e) {
                const click = new MouseEvent("click", {
                    bubbles: true,
                    cancelable: true,
                    view: window,
                });

                // 处理左右箭头切换下拉菜单
                if (e.key === "ArrowRight") {
                    const nextDropdown = getNextSibling(dropdownEl, '.dropdown');
                    if (!nextDropdown) {
                        document.querySelector('.dropdown-toggle').dispatchEvent(click);
                    } else {
                        nextDropdown.querySelector('.dropdown-toggle').dispatchEvent(click);
                    }
                } else if (e.key === "ArrowLeft") {
                    const prevDropdown = getPrevSibling(dropdownEl, '.dropdown');
                    if (!prevDropdown) {
                        const toggles = document.querySelectorAll('.dropdown-toggle');
                        toggles[toggles.length - 1].dispatchEvent(click);
                    } else {
                        prevDropdown.querySelector('.dropdown-toggle').dispatchEvent(click);
                    }
                } 
                // 处理菜单项快捷键
                else {
                    const pressedKey = e.key.toLowerCase();
                    if (hotkeyMap.has(pressedKey)) {
                        e.preventDefault(); // 阻止浏览器默认行为(如页面搜索)
                        hotkeyMap.get(pressedKey).dispatchEvent(click);
                        // 触发点击后关闭当前下拉菜单
                        dropdownEl.querySelector('.dropdown-toggle').dispatchEvent(new Event('hide.bs.dropdown'));
                    }
                }
            }

            // 添加键盘事件监听,下拉关闭时移除监听
            document.addEventListener('keydown', handleKeydown);
            dropdownEl.addEventListener('hidden.bs.dropdown', function removeListener() {
                document.removeEventListener('keydown', handleKeydown);
                dropdownEl.removeEventListener('hidden.bs.dropdown', removeListener);
            });
        });
    });
});

关键修改说明

  • 补全了原代码缺失的getNextSibling和getPrevSibling辅助函数,确保左右箭头切换功能正常运行
  • 修复了原代码中Xdropdown-toggle的拼写错误
  • 当下拉菜单展开时,自动提取菜单项中<u>标签的文本作为快捷键,构建不区分大小写的映射表
  • 在键盘事件监听中增加快捷键匹配逻辑,按下对应按键时直接触发菜单项点击,并自动关闭下拉菜单
  • 使用hidden.bs.dropdown事件移除键盘监听,替代原有的一次性监听,避免多次绑定导致的逻辑混乱
  • 添加e.preventDefault()阻止浏览器默认快捷键干扰(比如按A触发页面搜索)

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.19 17:25:06