将CSS hover事件转换为JavaScript点击事件以适配移动端多级下拉菜单
将CSS hover事件转换为JavaScript点击事件以适配移动端多级下拉菜单
我太懂你的困扰了——PC端靠CSS :hover做的多级下拉菜单用着顺风顺水,但移动端用户根本触发不了hover,换成点击逻辑是刚需,而且你之前用toggle时踩了多子菜单互斥的坑对吧?这就给你一套落地的解决方案:
第一步:重构CSS,用类替代hover控制显示
先把原来依赖hover的样式逻辑改成通过.active类来切换,这样JS只需要操作这个类就行,比直接改display更灵活也更好维护:
/* 初始状态:隐藏所有子菜单 */ .pages-links-sub div.dropdown-contentc { display: none; } .columnb-sub > .pages-links-sub { display: none; } /* 用.active类替代hover逻辑,控制子菜单显示 */ .columnb-sub.active > .pages-links-sub { display: block; } .columnb-sub.active > .pages-links-sub div.dropdown-contentc { display: block; }
第二步:用jQuery实现点击控制(解决多菜单互斥问题)
你之前用toggle出问题,核心是没处理「打开当前菜单时自动关闭其他所有菜单」的逻辑,下面的代码正好补上这个缺口:
$(document).ready(function() { // 给所有子菜单的触发按钮绑定点击事件 $('.columnb-sub > a').on('click', function(e) { // 阻止默认的锚点跳转行为(因为你的href是#) e.preventDefault(); // 获取当前点击的子菜单容器 const currentSubMenu = $(this).closest('.columnb-sub'); // 判断当前菜单是否处于展开状态 const isAlreadyActive = currentSubMenu.hasClass('active'); // 先统一关闭所有子菜单 $('.columnb-sub').removeClass('active'); // 如果当前菜单之前是收起的,就展开它;如果是展开的,就保持收起 if (!isAlreadyActive) { currentSubMenu.addClass('active'); } }); // 【可选优化】点击页面空白区域自动收起所有子菜单 $(document).on('click', function(e) { if (!$(e.target).closest('.columnb-sub').length) { $('.columnb-sub').removeClass('active'); } }); });
核心逻辑说明
- 点击子菜单触发链接时,先拦住默认的锚点跳转行为,避免页面抖一下
- 先把所有子菜单的
.active类移除,从根源保证同一时间只有一个子菜单能展开 - 再根据当前菜单的状态决定是否展开:收起状态就展开,展开状态就保持收起(实现toggle的交互)
- 空白区域点击关闭是加分项,能让用户操作更符合直觉
原生JavaScript版本(无需依赖jQuery)
要是你不想用jQuery,用原生JS也能实现完全一样的效果:
document.addEventListener('DOMContentLoaded', function() { // 获取所有子菜单触发按钮 const subMenuTriggers = document.querySelectorAll('.columnb-sub > a'); subMenuTriggers.forEach(trigger => { trigger.addEventListener('click', function(e) { e.preventDefault(); const currentSubMenu = this.closest('.columnb-sub'); const isAlreadyActive = currentSubMenu.classList.contains('active'); // 关闭所有子菜单 document.querySelectorAll('.columnb-sub').forEach(menu => { menu.classList.remove('active'); }); // 切换当前菜单状态 if (!isAlreadyActive) { currentSubMenu.classList.add('active'); } }); }); // 【可选优化】点击空白处关闭所有子菜单 document.addEventListener('click', function(e) { if (!e.target.closest('.columnb-sub')) { document.querySelectorAll('.columnb-sub').forEach(menu => { menu.classList.remove('active'); }); } }); });
改完之后不管是PC端点击还是移动端触摸,都能完美触发子菜单的展开/收起,完全解决了多菜单互斥的问题,和你原来的hover逻辑效果一致,只是触发方式换成了更适配移动端的点击~
备注:内容来源于stack exchange,提问作者Dion Fitzgerald
相关产品推荐
相关产品推荐

