Bootstrap 前端框架(或者说只是 UI 库)因为移动设备优先的问题,其 .dropdown 类即便在桌面级也需要点击才能展开,这个问题在互联网并没有找到特别适合的解决方案,故而打算自己实现。
通过观察展开和关闭的 DOM 变化, Bootstrap 5.x 通过 .show 类和 data-bs-popper="static" 来控制展开。
那么一个非常简单的方法,直接控制 .show 类和 data-bs-popper="static" 就可以实现鼠标悬浮来展开菜单。
首先,获取到所有 .dropdown 类,就像这样:
const bsDropdowns = document.querySelectorAll('.dropdown');
之后就可以编写主逻辑了:
bsDropdowns && bsDropdowns.forEach(i => { function add() { const menu = i.querySelector('.dropdown-menu'); if (menu) { menu.classList.add('show'); menu.setAttribute('data-bs-popper', 'static'); }; }; function remove() { const menu = i.querySelector('.dropdown-menu'); if (menu) { menu.classList.remove('show'); menu.removeAttribute('data-bs-popper'); }; }; i.addEventListener('mouseenter', add); i.addEventListener('click', add); i.addEventListener('mouseleave', remove); document.addEventListener('click', function (event) { !i.contains(event.target) && remove(); }); document.addEventListener('touchstart', function (event) { !i.contains(event.target) && remove(); }); });
这是一个非常简单的逻辑,其中定义了 add 和 remove 函数,它们的作用就是控制 .show 和 data-bs-popper 。
通过监听鼠标的 mouseenter 和 mouseleave 事件来确定移出和移入,并执行 add 或 remove 函数。
其中,
最后的监听滑动和点击事件都是为了弥补这段代码的缺陷问题,当滑动或点击目标不是 .dropdown 时就会关闭,与之前的保留点击展开结合,可以实现移动端 点击展开 和 点击其它位置或滑动其它位置关闭 的问题。
ZeoSeven 使用这段代码解决了项目的这一问题,项目使用的是 v5.3.3 ,包括 bootstrap.min.css 和 bootstrap.bundle.min.js ,所以这在 Bootstrap 5.x 中通常可以正常工作,在 v3.x 和 v4.x 中并不确定 ... 不过只要通过展开和关闭的 DOM 变化来确定控制展开和关闭的类或 data- 属性,那么这段代码只需修改 add 和 remove 函数的增加与删除目标,通常也可实现。