如何为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
相关产品推荐
相关产品推荐

