Element Plus 菜单组件区别和用法最佳实践
<div id="navCategory"><h5 class="catalogue">目录</h5><ul class="first_class_ul"><li><a href="#_label0">组件层级关系</a></li><li><a href="#_label1">1. el-menu - 菜单容器</a></li><ul class="second_class_ul"><li><a href="#_lab2_1_0">特性:</a></li><li><a href="#_lab2_1_1">基础用法:</a></li><li><a href="#_lab2_1_2">常用属性:</a></li></ul><li><a href="#_label2">2. el-menu-item - 菜单项</a></li><ul class="second_class_ul"><li><a href="#_lab2_2_3">特性:</a></li><li><a href="#_lab2_2_4">用法:</a></li><li><a href="#_lab2_2_5">关键点:</a></li></ul><li><a href="#_label3">3. el-sub-menu - 可展开的子菜单</a></li><ul class="second_class_ul"><li><a href="#_lab2_3_6">特性:</a></li><li><a href="#_lab2_3_7">用法:</a></li><li><a href="#_lab2_3_8">特殊功能:</a></li></ul><li><a href="#_label4">4. el-menu-item-group - 菜单项分组</a></li><ul class="second_class_ul"><li><a href="#_lab2_4_9">特性:</a></li><li><a href="#_lab2_4_10">用法:</a></li><li><a href="#_lab2_4_11">分组效果:</a></li></ul><li><a href="#_label5">完整示例对比</a></li><ul class="second_class_ul"></ul><li><a href="#_label6">选择指南</a></li><ul class="second_class_ul"></ul><li><a href="#_label7">最佳实践</a></li><ul class="second_class_ul"></ul></ul></div><p class="maodian"><a name="_label0"></a></p><h2>组件层级关系</h2><div class="jb51code"><pre class="brush:js;">el-menu (容器)
├── el-menu-item (直接可点击的选项)
├── el-sub-menu (可展开的父菜单)
│ ├── el-menu-item-group (分组容器,可选)
│ │ ├── el-menu-item (分组内的选项)
│ │ └── el-menu-item (分组内的选项)
│ ├── el-menu-item (未分组的选项)
│ └── el-sub-menu (嵌套子菜单,可无限级)
└── el-menu-item (其他选项)</pre></div>
<p class="maodian"><a name="_label1"></a></p><h2>1. el-menu - 菜单容器</h2>
<p class="maodian"><a name="_lab2_1_0"></a></p><p class="maodian"><a name="_lab2_2_3"></a></p><p class="maodian"><a name="_lab2_3_6"></a></p><p class="maodian"><a name="_lab2_4_9"></a></p><h3>特性:</h3>
<ul><li><strong>根容器</strong>:所有菜单组件的父容器</li><li><strong>控制整体行为</strong>:模式(垂直/水平)、主题、激活状态等</li><li><strong>管理状态</strong>:维护当前激活的菜单项</li></ul>
<p class="maodian"><a name="_lab2_1_1"></a></p><h3>基础用法:</h3>
<div class="jb51code"><pre class="brush:js;"><template>
<el-menu
:default-active="activeIndex"
class="el-menu-demo"
mode="horizontal"
@select="handleSelect"
>
<!-- 其他菜单组件 -->
</el-menu>
</template></pre></div>
<p class="maodian"><a name="_lab2_1_2"></a></p><h3>常用属性:</h3>
<div class="jb51code"><pre class="brush:js;"><el-menu
mode="horizontal|vertical" <!-- 模式:水平/垂直 -->
:default-active="currentIndex" <!-- 默认激活项 -->
:unique-opened="true" <!-- 是否只保持一个子菜单展开 -->
:collapse="isCollapse" <!-- 是否水平折叠收起菜单 -->
background-color="#545c64" <!-- 背景色 -->
text-color="#fff" <!-- 文字颜色 -->
active-text-color="#ffd04b" <!-- 激活文字颜色 -->
></pre></div>
<p class="maodian"><a name="_label2"></a></p><h2>2. el-menu-item - 菜单项</h2>
<h3>特性:</h3>
<ul><li><strong>叶子节点</strong>:通常是最后一级,可点击执行操作</li><li><strong>可激活状态</strong>:支持选中高亮</li><li><strong>支持图标和文本</strong></li></ul>
<p class="maodian"><a name="_lab2_2_4"></a></p><p class="maodian"><a name="_lab2_3_7"></a></p><p class="maodian"><a name="_lab2_4_10"></a></p><h3>用法:</h3>
<div class="jb51code"><pre class="brush:js;"><template>
<el-menu-item index="1" @click="handleClick">
<el-icon><House /></el-icon>
<span>首页</span>
</el-menu-item>
<!-- 带路由 -->
<el-menu-item index="2" :route="{ path: '/about' }">
<template #title>
<span>关于我们</span>
</template>
</el-menu-item>
<!-- 禁用状态 -->
<el-menu-item index="3" disabled>
<span>禁用项</span>
</el-menu-item>
</template></pre></div>
<p class="maodian"><a name="_lab2_2_5"></a></p><h3>关键点:</h3>
<ul><li><code>index</code> 属性必须唯一,用于标识和激活状态</li><li>通常绑定点击事件或路由跳转</li><li>不能包含子菜单组件</li></ul>
<p class="maodian"><a name="_label3"></a></p><h2>3. el-sub-menu - 可展开的子菜单</h2>
<h3>特性:</h3>
<ul><li><strong>父节点</strong>:可以包含子项</li><li><strong>可折叠</strong>:点击展开/收起子内容</li><li><strong>可嵌套</strong>:支持无限级嵌套</li></ul>
<h3>用法:</h3>
<div class="jb51code"><pre class="brush:js;"><template>
<el-sub-menu index="system">
<!-- 标题插槽 -->
<template #title>
<el-icon><Setting /></el-icon>
<span>系统管理</span>
</template>
<!-- 子内容 -->
<el-menu-item index="user">用户管理</el-menu-item>
<el-sub-menu index="log">
<template #title>日志管理</template>
<el-menu-item index="login-log">登录日志</el-menu-item>
</el-sub-menu>
</el-sub-menu>
</template></pre></div>
<p class="maodian"><a name="_lab2_3_8"></a></p><h3>特殊功能:</h3>
<div class="jb51code"><pre class="brush:js;"><!-- 带徽标 -->
<el-sub-menu index="messages">
<template #title>
<span>消息中心</span>
<el-badge :value="3" class="badge" />
</template>
</el-sub-menu>
<!-- 自定义展开图标 -->
<el-sub-menu index="custom">
<template #title>
<span>自定义</span>
</template>
<template #icon>
<el-icon><Star /></el-icon>
</template>
</el-sub-menu></pre></div>
<p class="maodian"><a name="_label4"></a></p><h2>4. el-menu-item-group - 菜单项分组</h2>
<h3>特性:</h3>
<ul><li><strong>分组容器</strong>:用于对菜单项进行逻辑分组</li><li><strong>仅视觉分隔</strong>:不影响功能逻辑</li><li><strong>显示分组标题</strong></li></ul>
<h3>用法:</h3>
<div class="jb51code"><pre class="brush:js;"><template>
<el-sub-menu index="settings">
<template #title>设置</template>
<!-- 分组1 -->
<el-menu-item-group title="账户设置">
<el-menu-item index="profile">个人信息</el-menu-item>
<el-menu-item index="security">安全设置</el-menu-item>
</el-menu-item-group>
<!-- 分组2 -->
<el-menu-item-group title="系统设置">
<el-menu-item index="theme">主题设置</el-menu-item>
<el-menu-item index="notification">通知设置</el-menu-item>
</el-menu-item-group>
<!-- 未分组的项 -->
<el-menu-item index="help">帮助中心</el-menu-item>
</el-sub-menu>
</template></pre></div>
<p class="maodian"><a name="_lab2_4_11"></a></p><h3>分组效果:</h3>
<div class="jb51code"><pre class="brush:js;">┌─────────────────┐
│ 账户设置 │← 分组标题
├─────────────────┤
│个人信息 │
│安全设置 │
├─────────────────┤
│ 系统设置 │← 分组标题
├─────────────────┤
│主题设置 │
│通知设置 │
├─────────────────┤
│帮助中心 │← 未分组项
└─────────────────┘</pre></div>
<p class="maodian"><a name="_label5"></a></p><h2>完整示例对比</h2>
<div class="jb51code"><pre class="brush:js;"><template>
<el-menu default-active="2-2" class="menu-container">
<!-- 1. 直接菜单项 -->
<el-menu-item index="1">
<el-icon><House /></el-icon>
<span>首页</span>
</el-menu-item>
<!-- 2. 带子菜单 -->
<el-sub-menu index="2">
<template #title>
<el-icon><Folder /></el-icon>
<span>文档中心</span>
</template>
<!-- 2.1 未分组的项 -->
<el-menu-item index="2-1">快速开始</el-menu-item>
<!-- 2.2 分组1 -->
<el-menu-item-group title="用户指南">
<el-menu-item index="2-2">安装指南</el-menu-item>
<el-menu-item index="2-3">使用教程</el-menu-item>
</el-menu-item-group>
<!-- 2.3 分组2 -->
<el-menu-item-group title="API参考">
<el-menu-item index="2-4">组件API</el-menu-item>
<el-menu-item index="2-5">方法参考</el-menu-item>
</el-menu-item-group>
<!-- 2.4 嵌套子菜单 -->
<el-sub-menu index="2-6">
<template #title>高级主题</template>
<el-menu-item index="2-6-1">性能优化</el-menu-item>
<el-menu-item index="2-6-2">最佳实践</el-menu-item>
</el-sub-menu>
</el-sub-menu>
<!-- 3. 另一个直接菜单项 -->
<el-menu-item index="3">
<el-icon><InfoFilled /></el-icon>
<span>关于</span>
</el-menu-item>
</el-menu>
</template></pre></div>
<p class="maodian"><a name="_label6"></a></p><h2>选择指南</h2>
<table><thead><tr><th>场景</th><th>选择组件</th><th>说明</th></tr></thead><tbody><tr><td>直接跳转/操作</td><td><code>el-menu-item</code></td><td>不需要下级菜单</td></tr><tr><td>有子选项</td><td><code>el-sub-menu</code></td><td>需要展开显示子项</td></tr><tr><td>子项需要分类</td><td><code>el-menu-item-group</code> + <code>el-menu-item</code></td><td>视觉上分组</td></tr><tr><td>多级嵌套</td><td><code>el-sub-menu</code> 嵌套</td><td>无限层级</td></tr><tr><td>只是容器</td><td><code>el-menu</code></td><td>最外层容器</td></tr></tbody></table>
<p class="maodian"><a name="_label7"></a></p><h2>最佳实践</h2>
<ul><li><strong>保持层级清晰</strong>:不建议超过3级嵌套</li><li><strong>合理使用分组</strong>:当有5个以上子项时考虑分组</li><li><strong>索引命名规范</strong>:使用层级命名如 <code>1-2-1</code></li><li><strong>响应式考虑</strong>:深层次菜单在移动端体验差</li><li><strong>配合路由使用</strong>:</li></ul>
<div class="jb51code"><pre class="brush:js;"><el-menu
:default-active="$route.path"
router
@select="handleSelect"
>
<el-menu-item index="/dashboard" :route="{ path: '/dashboard' }">
仪表盘
</el-menu-item>
</el-menu></pre></div>
<p>这些组件共同构成了 Element Plus 强大的菜单系统,可以根据不同需求灵活组合使用。</p> 回复:
感谢楼主的分享!
看完这篇教程,感觉对Element Plus的菜单组件有了更清晰的认识。之前在使用的时候总是搞不清楚什么时候用el-sub-menu,什么时候用el-menu-item-group,现在终于搞明白了!
几点感受:
[*]层级关系那部分总结得特别好,一眼就能看出各个组件的包含关系
[*]选择指南的表格很实用,以后开发时可以直接对照着选
[*]最佳实践那几点也很中肯,尤其是不要超过3级嵌套,之前没注意这点
想请教一下:
如果我想实现这种效果:点击一级菜单项本身也能触发事件,同时还能展开子菜单,这种需求该怎么实现呢?试过用el-sub-menu但是点击标题好像只能展开菜单。
还有就是collapse属性在配合router模式使用时,有没有什么需要注意的坑?
总之是一篇很干货的帖子,收藏了!希望楼主多多分享Element Plus的其他组件使用心得~ 楼主这篇整理得太到位了!必须前排支持一下!
之前做后台管理系统的时候,菜单这块确实踩了不少坑,特别是动态渲染和分组混用的时候,经常搞得样式错乱或者点击没反应。看完你的层级梳理,瞬间通透了,逻辑清晰很多。
结合我自己的实战经历,补充几点小建议:
[]开启 router 模式后,直接绑定路由路径能省掉大量手动跳转的代码,配合 unique-opened 属性体验更好
[]自定义图标时建议统一用 el-icon 包裹,不然默认基线对不齐会显得特别别扭
[*]如果菜单数据是从后端动态下发的,记得在组件挂载前做好树形结构递归处理,不然子级一多容易渲染报错
顺便想请教下各位大佬:
在做响应式布局时,如果屏幕宽度变小,多级菜单展开很容易挤占主内容区。大家一般是直接切换成 el-drawer 侧滑面板替代,还是有什么平滑的折叠过渡方案?求指点!
再次感谢干货分享,已收藏备用,以后写组件直接参考这篇啦~1
頁:
[1]