最稳妥结构是用 包裹 +,每个菜单项为 文本,二级菜单嵌套 并配 aria-haspopup="true" 和 aria-expanded="false"。

左侧菜单用什么 HTML 结构最稳妥
直接用 <nav></nav> 包裹 <ul></ul> + <li> 是最通用、语义正确且无障碍友好的选择。别用 <div> 堆砌,否则屏幕阅读器识别困难,后续加权限控制或键盘导航也容易出问题。
<p>常见错误是把菜单项写成一堆独立的 <code>@#@#@#@#@#@#@#@#@#@0,不推荐用 <button></button> 模拟跳转(会破坏原生链接语义和 SEO)
<ul></ul>,并给父级 <li> 加 aria-haspopup="true" 和 aria-expanded="false"
怎么让菜单支持展开/收起又不卡顿
纯 CSS 实现折叠(比如用 :hover 或 details/summary)看似简单,但实际项目里几乎不可用:移动端没 hover、无法记忆展开状态、没法配合路由高亮。必须用 JS 控制,但关键是要避免每次点击都重绘整个菜单树。
- 只对被点击的
<li>切换aria-expanded和对应子菜单的display或max-height,别用innerHTML重写整块 DOM - 子菜单用
max-height: 0+overflow: hidden+transition: max-height 0.2s ease实现平滑动画,比height更可靠(height: auto无法过渡) - 如果菜单项超过 50 条,考虑虚拟滚动或懒加载子菜单 HTML 片段,否则首次渲染明显延迟
菜单高亮怎么和当前路由真正对齐
后端渲染页面时,通常靠服务端模板(如 Thymeleaf、Jinja)在生成 HTML 时就写死 class="active";但前后端分离项目里,JS 必须根据当前 URL 主动匹配并添加 class,否则点击跳转后菜单还是旧状态。
如果你了解HTML,CSS和JavaScript,您已经拥有所需的工具开发Android应用程序。本动手本书展示了如何使用这些开源web标准设计和建造,可适应任何Android设备的应用程序 - 无需使用Java。您将学习如何创建一个在您选择的平台的Android友好的网络应用程序,然后转换与自由PhoneGap框架到一个原生的Android应用程序。了解为什么设备无关的移动应用是未来的潮流,并开始构建应用程序,提供更
- 不要只比对
window.location.pathname是否包含/user——这样 /user/edit 也会激活 /user/list,造成误亮 - 推荐用精确前缀匹配:
pathname.startsWith('/user/list'),或者用正则^/user/list(/|$) - 如果用了前端路由(如 Vue Router、React Router),直接读取路由实例的
currentRoute.value.path或useLocation().pathname,比操作window.location更可靠 - 注意哈希模式(
#/user/list)下要解析location.hash,不是pathname
权限控制该在菜单渲染前还是渲染后做
必须在菜单数据**渲染前**过滤。渲染后再用 JS 隐藏元素,不仅浪费 DOM 节点,还可能因权限逻辑缺陷暴露未授权入口(比如按钮隐藏但 API 仍可调用)。
- 菜单配置数据本身应带
permissionCode字段(如"user:read"),前端初始化时用当前用户权限列表做一次filter - 后端返回的菜单 JSON 就该是过滤后的结果——这是更安全的做法,前端只做二次校验,不作为唯一依据
- 别在
v-if或{% if %}里写复杂权限表达式(如user.role === 'admin' || hasPerm('order:export')),提取成独立函数复用,避免模板臃肿
菜单看着简单,但路由匹配精度、权限过滤时机、DOM 更新性能这三点,任何一个没踩准,上线后就会反复修 bug。尤其权限和路由联动的部分,很容易测试覆盖不到。










