jQuery三级菜单应使用嵌套结构与事件委托实现,通过$(this).next('ul').slideToggle()控制展开,配合CSS display:none和toggleClass翻转图标,需主动清理子级菜单并处理iOS兼容性问题。

直接用 jQuery + 语义化 <ul></ul> 嵌套就能稳住三级菜单的折叠逻辑,不依赖框架、不写递归、不手动维护状态类 —— 关键是事件委托和层级选择器要写对。
HTML 结构必须用嵌套 <ul></ul>,不能靠 class 模拟层级
浏览器原生不识别 “三级菜单” 这个概念,全靠 DOM 嵌套关系驱动。错误做法是给每个子菜单加独立 class(如 .menu-level-2、.menu-level-3),这会导致 JS 控制混乱、CSS 难复用。
- 一级菜单项用
<li>直接放在顶层<ul></ul>中 - 带子菜单的项统一加
class="sub-menu",其子<ul></ul>就是下一级菜单 - 二级菜单里的
<li class="sub-menu">内部再嵌<ul></ul>,自然构成三级 —— 不需要额外标记 -
<a></a>标签必须保留href(哪怕为#),否则键盘 Tab 和屏幕阅读器会跳过
jQuery 绑定要用事件委托,避免重复绑定或漏绑
如果用 $('li.sub-menu > a').on('click', ...) 直接绑定,新插入的菜单项(比如异步加载后)不会响应;而用 .on() 委托到父容器才能一劳永逸。
- 把事件委托到最外层
<nav></nav>或<ul></ul>,例如:$('nav.vertical-nav').on('click', 'li.sub-menu > a', function(e) {...}) - 点击时只操作紧邻的下一个
<ul></ul>:$(this).next('ul').slideToggle(200),不查所有后代<ul></ul> - 阻止默认跳转但保留锚点语义:
e.preventDefault()即可,不用删href - 图标翻转用
toggleClass('fa-caret-down fa-caret-up'),别用addClass/removeClass手动切换
CSS 必须用 display: none + overflow: hidden 配合 slideToggle
slideToggle() 依赖元素高度从 0 → auto 的过渡,如果子菜单用了 visibility: hidden 或 opacity: 0,动画会失效或卡顿。
立即学习“前端免费学习笔记(深入)”;
- 所有子菜单初始状态设为:
ul { display: none; },不要用height: 0或max-height - 父级
<li>不要设overflow: hidden,否则slideToggle动画会被截断 - 箭头图标用
float: right或margin-left: auto排版,避免影响<a></a>宽度计算 - 若需禁用某级展开(比如三级菜单不允许再展开),就别给对应
<li>加sub-menu类 —— 别靠 JS 判断层级数来拦截
移动端点击穿透和 Safari 滚动抖动要单独处理
iOS Safari 对 touchstart + click 混用敏感,容易导致点一次触发两次,或滑动时误触展开。
- 在
click回调开头加判断:if ('ontouchstart' in window && e.type === 'click') return;,改用touchstart事件替代(但保留click兜底) - 给
nav.vertical-nav加touch-action: manipulation,减少 iOS 300ms 延迟和滚动冲突 - 如果菜单在
position: fixed侧边栏里,Safari 可能因重绘抖动,加transform: translateZ(0)强制 GPU 加速 - 别在
slideToggle动画中同时修改大量样式(比如动态加 class 控制颜色),优先用 CSS 类切换
真正难的不是写三层结构,而是让第二级收起时,它内部已展开的第三级自动闭合 —— 这得靠 $(this).next('ul').find('ul').slideUp() 主动清理,而不是指望用户手动点回去。



















