jQuery中鼠标悬停子菜单时无法保持显示的问题排查
问题原因及解决方案
核心问题出在HTML结构不符合规范,<ul>的直接子元素只能是<li>,你当前把.issues子菜单和父级<li>同级放置,导致鼠标从Issues标签的<li>移到子菜单时,会触发父<li>的mouseleave事件;同时子菜单不在父<li>的范围内,即便设置了setTimeout和clearTimeout,也会因为事件触发逻辑或鼠标移动路径的问题,导致子菜单立刻消失。
修正后的完整代码
HTML(修复结构,子菜单嵌套进父li)
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script> <nav> <ul> <li> <a>Issues</a> <ul class="issues"> <li><a>X</a></li> <li><a>Y</a></li> <li><a>Z</a></li> </ul> </li> <li><a>Press Releases</a></li> <li><a>Donate</a></li> </ul> </nav>
JavaScript(优化事件逻辑)
let timeout; // 父li的鼠标进入/点击事件:显示子菜单,清除之前的超时 $('nav > ul li:first-child').on('mouseenter click', function () { clearTimeout(timeout); $('.issues').slideDown('slow'); }).on('mouseleave', function () { // 离开父li时,3秒后收起子菜单 timeout = setTimeout(function () { $('.issues').slideUp(); }, 3000); }); // 子菜单的鼠标进入事件:清除超时,保持显示 $('.issues').on('mouseenter', function() { clearTimeout(timeout); }).on('mouseleave', function() { // 离开子菜单时,3秒后收起 timeout = setTimeout(function () { $('.issues').slideUp(); }, 3000); });
CSS(可保持原设置)
.issues { display: none; position: static; margin-top: 0; padding-left: 0; }
逻辑说明
- 修复HTML结构后,子菜单成为父
<li>的一部分,鼠标在父标签和子菜单之间移动时,不会触发父<li>的mouseleave事件,从根源避免了误触发收起的问题。 - 新增子菜单的
mouseleave处理,确保离开子菜单后仍能延迟3秒收起;同时在所有显示子菜单的操作中先清除超时,防止之前的延迟任务导致意外收起。
内容的提问来源于stack exchange,提问作者user10673486
相关产品推荐
相关产品推荐

