资讯动态

Element Plus Menu 导航菜单组件完全指南:水平/垂直模式、折叠与完整 API 详解

发布时间:2026/9/11 9:08:19 来源:尧图企业网站定制
Element Plus Menu 导航菜单组件完全指南水平/垂直模式、折叠与完整 API 详解【免费下载链接】element-plus A Vue.js 3 UI Library made by Element team项目地址: https://gitcode.com/GitHub_Trending/el/element-plusMenu 是 Element Plus 中提供网站导航能力的核心组件支持顶部导航栏水平模式与侧边栏垂直模式两大形态并内置子菜单、菜单分组、折叠、省略号溢出、Popper 弹层等能力。本文将基于docs/en-US/component/menu.md官方文档为骨架结合packages/components/menu下的源码实现与docs/examples/menu中的可运行示例带你系统掌握 Menu 的每种布局模式、全部配置项与类型声明并理解其底层如何工作。覆盖默认高度CSS 变量定制Menu 的水平模式高度由主题变量--el-menu-horizontal-height控制默认值为 44px由主题文件packages/theme-chalk/src/menu.scss中定义。如果你需要覆盖水平菜单的默认高度直接在对应元素上覆写该 CSS 变量即可官方文档给出的示例如下.el-menu--horizontal { --el-menu-horizontal-height: 100px; }这一方案利用了 CSS 自定义属性的继承机制——el-menu渲染为ul classel-menu el-menu--horizontal见 menu.ts 渲染逻辑类名选择器.el-menu--horizontal的优先级足够覆盖主题中的默认声明且不会影响垂直模式。类似地主题还提供--el-menu-hover-bg-color、--el-menu-active-color、--el-menu-text-color等 CSS 变量用于定制 hover、激活、文字颜色具体声明可查看 use-menu-css-var.ts。顶部导航栏水平模式顶栏菜单适用于站点导航、工作台顶部的多级菜单等场景。默认情况下 Menu 是垂直的将mode属性设为horizontal即可切换为水平模式再配合el-sub-menu子菜单组件即可构建二级乃至多级菜单。官方文档还提到可通过background-color、text-color与active-text-color自定义配色这三个属性已被标记为 deprecated推荐改用 CSS 变量方案。完整的可运行示例见 basic.vue核心结构如下template el-menu :default-activeactiveIndex classel-menu-demo modehorizontal selecthandleSelect el-menu-item index1Processing Center/el-menu-item el-sub-menu index2 template #titleWorkspace/template el-menu-item index2-1item one/el-menu-item el-menu-item index2-2item two/el-menu-item el-sub-menu index2-4 template #titleitem four/template el-menu-item index2-4-1item one/el-menu-item el-menu-item index2-4-2item two/el-menu-item el-menu-item index2-4-3item three/el-menu-item /el-sub-menu /el-sub-menu el-menu-item index3 disabledInfo/el-menu-item el-menu-item index4Orders/el-menu-item /el-menu !-- 深色背景 自定义配色版本 -- el-menu :default-activeactiveIndex2 classel-menu-demo modehorizontal background-color#545c64 text-color#fff active-text-color#ffd04b selecthandleSelect !-- 菜单项结构同上 -- /el-menu /template script langts setup import { ref } from vue const activeIndex ref(1) const activeIndex2 ref(1) const handleSelect (key: string, keyPath: string[]) { console.log(key, keyPath) } /script几点实操要点index是唯一标识菜单项与子菜单通过index字符串建立一一对应关系它是 Menu 内部注册表items/subMenus两个以 index 为 key 的 Map的键见 menu.ts 中的 addMenuItem/addSubMenu。default-active的值必须与某个index匹配激活态才会生效。#title具名插槽子菜单的标题通过#title插槽提供菜单项在折叠场景下也可以使用#title插槽详见折叠一节。disabled直接禁用el-menu-item index3 disabled会阻止点击与 hover 展开。配色属性已弃用background-color/text-color/active-text-color在源码中均带有deprecated标注见 menu.ts建议改用样式类配合--el-menu-bg-color、--el-menu-text-color、--el-menu-active-color变量。从源码层面看水平模式与垂直模式的最大差异在于isMenuPopup计算属性当mode horizontal或「垂直 折叠」时子菜单不再以内联方式展开而是渲染为基于ElTooltip的 Popup 浮层placement 为bottom-start见 sub-menu.ts 的 currentPlacement 逻辑。此外水平模式在onMounted时还会通过new Menubar(...)menu-bar.ts初始化键盘导航与 hover 行为。左对齐与右对齐布局顶栏菜单经常需要「Logo 在左、操作项在右」的布局。官方示例 left-and-right.vue 展示的做法是将第一个菜单项通过 CSSmargin-right: auto推向左端其余菜单项自然挤到右侧template el-menu :default-activeactiveIndex classel-menu-demo modehorizontal :ellipsisfalse selecthandleSelect el-menu-item index0 img stylewidth: 100px src/images/element-plus-logo.svg altElement logo / /el-menu-item el-menu-item index1Processing Center/el-menu-item el-sub-menu index2 template #titleWorkspace/template !-- ... -- /el-sub-menu /el-menu /template style scoped .el-menu--horizontal .el-menu-item:nth-child(1) { margin-right: auto; } /style注意该示例同时设置了:ellipsisfalse——因为 Logo 图片的宽度较大如果保持默认的ellipsis: trueMenu 的溢出省略逻辑可能会把超出宽度的项收进更多下拉中。ellipsis的行为在源码中由calcSliceIndex完成它遍历菜单的所有子节点逐项累加宽度含 margin当累计宽度超过「菜单宽度 − 更多按钮宽度」时记录截断位置sliceIndex超出部分被包进一个 index 为sub-menu-more的省略号子菜单见 menu.ts。垂直侧边栏带子菜单分组垂直菜单是最典型的后台管理侧边栏形态。官方示例 vertical.vue 展示了用el-sub-menu构建可展开/收起的多级子菜单用el-menu-item-group对菜单项进行分组分组标题由title属性或具名插槽决定菜单项内可放置el-icon与文字组合的常见侧边栏样式。template el-row classtac el-col :span12 h5 classmb-2Default colors/h5 el-menu default-active2 classel-menu-vertical-demo openhandleOpen closehandleClose el-sub-menu index1 template #title el-iconlocation //el-icon spanNavigator One/span /template el-menu-item-group titleGroup One el-menu-item index1-1item one/el-menu-item el-menu-item index1-2item two/el-menu-item /el-menu-item-group el-menu-item-group titleGroup Two el-menu-item index1-3item three/el-menu-item /el-menu-item-group el-sub-menu index1-4 template #titleitem four/template el-menu-item index1-4-1item one/el-menu-item /el-sub-menu /el-sub-menu el-menu-item index2 el-iconicon-menu //el-icon spanNavigator Two/span /el-menu-item el-menu-item index3 disabled el-icondocument //el-icon spanNavigator Three/span /el-menu-item el-menu-item index4 el-iconsetting //el-icon spanNavigator Four/span /el-menu-item /el-menu /el-col !-- 右侧为自定义配色版本结构相同 -- /el-row /template值得关注的实现细节分组渲染el-menu-item-group渲染为li classel-menu-item-group组标题由titleprop 或#title插槽渲染内部菜单项包裹在ul classel-menu-item-group__list中见 menu-item-group.vue。indexPath 自底向上推导子菜单的indexPath由useMenu组合式函数计算——从当前组件实例沿instance.parent向上遍历直到找到ElMenu根组件沿途收集带index的祖先形成如[1, 1-4, 1-4-1]的路径数组见 use-menu.ts。这个路径正是open/close/select事件回调的第二参数。父级激活联动子菜单的active状态并非只看自己而是检查其内部所有菜单项与子菜单是否处于激活态[...Object.values(items), ...Object.values(subMenus)].some(...)见 sub-menu.ts因此选中三级菜单时其所有祖先子菜单都会高亮。菜单折叠Collapse垂直菜单支持折叠为只显示图标的窄条形态通过collapse属性控制。官方示例 collapse.vue 用一个el-radio-group切换折叠状态template el-radio-group v-modelisCollapse stylemargin-bottom: 20px el-radio-button :valuefalseexpand/el-radio-button el-radio-button :valuetruecollapse/el-radio-button /el-radio-group el-menu default-active2 classel-menu-vertical-demo :collapseisCollapse openhandleOpen closehandleClose el-sub-menu index1 template #title el-iconlocation //el-icon spanNavigator One/span /template el-menu-item-group template #titlespanGroup One/span/template el-menu-item index1-1item one/el-menu-item /el-menu-item-group el-sub-menu index1-4 template #titlespanitem four/span/template el-menu-item index1-4-1item one/el-menu-item /el-sub-menu /el-sub-menu el-menu-item index2 el-iconicon-menu //el-icon template #titleNavigator Two/template /el-menu-item el-menu-item index3 disabled el-icondocument //el-icon template #titleNavigator Three/template /el-menu-item el-menu-item index4 el-iconsetting //el-icon template #titleNavigator Four/template /el-menu-item /el-menu /template style .el-menu-vertical-demo:not(.el-menu--collapse) { width: 200px; min-height: 400px; } /style折叠场景的关键规则折叠时#title插槽用于 Tooltip 内容折叠状态下菜单项与子菜单的文字标题被隐藏只剩图标此时标题文本要放到#title插槽中折叠后鼠标悬停时它会被渲染成 Tooltip 提示内容popper-effect默认dark主题。展开/收起图标成对出现expand-close-icon与expand-open-icon必须成对传入才生效对应展开模式下子菜单关闭/打开时的图标collapse-close-icon与collapse-open-icon同理对应折叠模式。源码中subMenuTitleIcon计算属性按此规则取舍缺省时水平/展开模式使用ArrowDown、垂直/折叠模式使用ArrowRight见 sub-menu.ts。折叠时子菜单切换为 PopupisMenuPopup在垂直折叠时同样为true此时子菜单列表以 Tooltip 浮层形式弹出动画为el-zoom-in-left。折叠动画可关闭collapse-transition默认为true源码在mode vertical时用ElMenuCollapseTransition包裹整个ul见 menu-collapse-transition.vue设置:collapse-transitionfalse可禁用。折叠即关闭源码watch(() props.collapse)会在折叠时清空openedMenus避免折叠后残留展开状态同时外层ul以key: String(props.collapse)强制重新渲染保证折叠/展开切换时的 DOM 一致性。Popper 偏移量Popper Offset自 2.4.4 起Menu 与 SubMenu 都支持popper-offset用于控制子菜单 Popup 浮层与触发标题之间的间距。菜单级popper-offset默认值为 6见 menu.ts 中 menuProps.popperOffset对所有子菜单生效而单个el-sub-menu上的popper-offset可以覆盖菜单级配置且支持多级递归覆盖。官方示例 popper-offset.vue 演示了三级覆盖关系el-menu ellipsis classel-menu-popper-demo modehorizontal :popper-offset16 stylemax-width: 600px el-menu-item index1Processing Center/el-menu-item el-sub-menu index2 !-- 未设置 popper-offset继承菜单级的 16 -- /el-sub-menu el-sub-menu index3 :popper-offset8 template #titleOverride Popper Offset/template el-menu-item index3-1item one/el-menu-item el-sub-menu index3-4 :popper-offset20 template #titleoverride child/template !-- 再嵌套覆盖为 20 -- /el-sub-menu /el-sub-menu el-menu-item index4 disabledInfo/el-menu-item el-menu-item index5Orders/el-menu-item /el-menu其覆盖优先级在源码中体现得很直接const subMenuPopperOffset computed( () props.popperOffset ?? rootMenu.props.popperOffset )??空值合并意味着子菜单显式传入popper-offset时使用自身值未传入时回退到根 Menu 的配置见 sub-menu.ts。最终该值被透传给内部ElTooltip的offset属性。同级的popper-class、popper-style、show-timeout、hide-timeout也都采用这种「子组件优先缺省继承 Menu」的透传策略。Menu API 详解以下内容完整对应官方文档的 API 章节并结合 menu.ts 源码给出默认值佐证。Menu Attributes名称说明类型默认值mode菜单展示模式horizontal \| verticalverticalcollapse是否折叠仅垂直模式可用booleanfalseellipsis是否省略溢出项仅水平模式可用booleantrueellipsis-icon ^(2.4.4)自定义省略号图标仅水平模式且ellipsis为 true 时可用string / ComponentMore图标popper-offset ^(2.4.4)Popup 浮层偏移量对所有子菜单生效number6default-active页面加载时激活菜单项的 indexstringdefault-openeds包含当前展开子菜单 index 的数组string[][]unique-opened是否只允许同时展开一个子菜单booleanfalsemenu-trigger子菜单触发方式仅mode为 horizontal 时生效hover \| clickhoverrouter是否启用vue-router模式。为 true 时index 将作为路由 path 触发路由跳转可与default-active配合在加载时设置激活项booleanfalsecollapse-transition是否启用折叠动画booleantruepopper-effect ^(2.2.26)折叠时弹出层的 Tooltip 主题内置dark/lightdark \| light / stringdarkclose-on-click-outside ^(2.4.4)点击菜单外部区域时是否收起菜单booleanfalsepopper-class ^(2.5.0)所有弹出菜单与标题 Tooltip 的自定义类名string—popper-style ^(2.11.5)所有弹出菜单与标题 Tooltip 的自定义样式string / object—show-timeout ^(2.5.0)所有菜单显示前的延时控制number300hide-timeout ^(2.5.0)所有菜单隐藏前的延时控制number300background-color ^(deprecated)菜单背景色hex 格式已弃用请在样式类中使用--el-menu-bg-colorstring#fffffftext-color ^(deprecated)菜单文字色hex 格式已弃用请在样式类中使用--el-menu-text-colorstring#303133active-text-color ^(deprecated)当前激活菜单项文字色hex 格式已弃用请在样式类中使用--el-menu-active-colorstring#409effpersistent ^(2.9.5)菜单处于非激活状态且persistent为false时下拉菜单将被销毁booleantrue源码佐证与使用提示mode通过values: [horizontal, vertical]约束取值非法值会触发 Vue 的 props 校验警告。default-openeds只作用于垂直模式且仅在非折叠状态下生效props.defaultOpeneds !props.collapse才初始化openedMenus。unique-opened的实现见openMenu展开新子菜单时会用openedMenus.filter(index indexPath.includes(index))收掉不在当前路径上的其它已展开菜单menu.ts。router模式下点击菜单项会执行router.push(route || index)并将routerResultPromise作为select事件的第四个参数传出只有路由跳转成功res非空才更新activeIndex见 menu.ts 的 handleMenuItemClick。close-on-click-outside通过ClickOutside指令实现点击外部时若不在子菜单内!mouseInChild.value则对所有已展开子菜单逐个触发close事件并清空openedMenus。三个颜色属性的弃用路径它们会经 use-menu-css-var.ts 映射为--el-menu-text-color、--el-menu-bg-color、--el-menu-active-color等 CSS 变量hover-bg-color由背景色 shade 20% 计算而来见 use-menu-color.ts。建议直接在样式类中覆盖这些变量而非使用 prop。Menu Events名称说明类型select菜单项被激活时的回调MenuSelectEventopen子菜单展开时的回调MenuOpenEventclose子菜单收起时的回调MenuCloseEvent三个事件都会携带(index, indexPath)select额外携带被点击的菜单项对象启用router时还带有routerResultPromise。事件对象的具体签名见下文 Type Declarations。源码中menuEmits对每个事件都编写了运行时校验器例如select要求index为字符串、indexPath为字符串数组、item为对象且routerResult为 Promise 或 undefined。Menu Slots名称说明子标签default自定义默认内容SubMenu / Menu-Item / Menu-Item-GroupMenu Exposes名称说明类型open打开指定子菜单参数为子菜单 index(index: string) voidclose关闭指定子菜单参数为子菜单 index(index: string) voidhandleResize手动触发菜单宽度重算() voidupdateActiveIndex ^(2.9.8)设置激活菜单的 index(index: string) void这些方法对应源码中expose({ open, close, updateActiveIndex, handleResize })见 menu.ts。handleResize触发时通过ResizeObserver配合 33.34ms 防抖按 60Hz 刷新率1000/60×2计算重算省略号截断位置首帧渲染直接执行以避免抖动。SubMenu APISubMenu Attributes名称说明类型默认值index ^(required)唯一标识string—popper-class弹出菜单的自定义类名string—popper-style ^(2.11.5)弹出菜单的自定义样式string / object—show-timeout子菜单显示前延时默认继承 Menu 的show-timeoutnumber—hide-timeout子菜单隐藏前延时默认继承 Menu 的hide-timeoutnumber—disabled是否禁用该子菜单booleanfalseteleported弹出菜单是否 teleport 到 body一级子菜单默认为 true其余层级默认为 falsebooleanundefinedpopper-offsetPopup 浮层偏移量覆盖 Menu 的popper-offsetnumber—expand-close-icon展开模式下子菜单关闭时的图标需与expand-open-icon成对传入string / Component—expand-open-icon展开模式下子菜单打开时的图标需与expand-close-icon成对传入string / Component—collapse-close-icon折叠模式下子菜单关闭时的图标需与collapse-open-icon成对传入string / Component—collapse-open-icon折叠模式下子菜单打开时的图标需与collapse-close-icon成对传入string / Component—源码说明见 sub-menu.tsteleported的默认行为isUndefined(value) ? isFirstLevel.value : value即不传时一级子菜单跟随 Menu 弹出到 body嵌套层级子菜单则就近渲染这与 Tooltip 浮层避免被父级overflow: hidden裁剪的常见需求对应。show-timeout/hide-timeout对应 hover 进出时useTimeoutFn的延时控制鼠标移入子菜单 Popup 内容时延时会被缩短为 100ms提升多级菜单的悬停连贯性。弹出位置currentPlacement水平模式一级子菜单为bottom-start其余层级含垂直折叠为right-startfallbackPlacements提供了一组按空间自适应回退的候选位置。SubMenu Slots名称说明子标签default自定义默认内容SubMenu / Menu-Item / Menu-Item-Grouptitle自定义标题内容—Menu-Item APIMenu-Item Attributes名称说明类型默认值index ^(required)唯一标识string—routeVue Router 路由位置参数string / object—disabled是否禁用booleanfalseroute的类型为RouteLocationRawstring | object在router模式下会作为router.push的目标优先级高于index字符串const route menuItem.route || index见 menu.ts。props 声明位于 menu-item.ts。Menu-Item Events名称说明类型click菜单项被点击时的回调参数为菜单项实例(item: MenuItemRegistered) voidMenu-Item Slots名称说明default自定义默认内容title自定义标题内容折叠模式下显示在 Tooltip 中Menu-Item-Group APIMenu-Item-Group Attributes名称说明类型默认值title分组标题string—Menu-Item-Group Slots名称说明子标签default自定义默认内容Menu-Itemtitle自定义分组标题—分组标题既可以用titleprop 声明如el-menu-item-group titleGroup One也可以用#title插槽定制见 menu-item-group.vue。类型声明Type Declarations官方文档在details折叠区给出了完整类型声明与 types.ts 中的接口一一对应供 TS 用户按需引用/** * param index index of activated menu * param indexPath index path of activated menu * param item the selected menu item * param routerResult result returned by vue-router if router is enabled */ type MenuSelectEvent ( index: string, indexPath: string[], item: MenuItemClicked, routerResult?: Promisevoid | NavigationFailure ) void /** * param index index of expanded sub-menu * param indexPath index path of expanded sub-menu */ type MenuOpenEvent (index: string, indexPath: string[]) void /** * param index index of collapsed sub-menu * param indexPath index path of collapsed sub-menu */ type MenuCloseEvent (index: string, indexPath: string[]) void interface MenuItemRegistered { index: string indexPath: string[] active: boolean } interface MenuItemClicked { index: string indexPath: string[] route?: RouteLocationRaw }其中NavigationFailure与RouteLocationRaw来自vue-router即启用router模式时需要安装并配置 Vue Router。indexPath的语义与前面useMenu推导的路径一致它是从一级到当前项的完整索引链例如点击2-4-1时得到[2, 2-4, 2-4-1]非常适合在select回调中判断用户位于导航的哪个分支。综合示例侧边栏 路由 折叠的实战组合将上文要点组合即可得到后台系统最常见的侧边栏形态垂直菜单 router路由联动 折叠切换。以下代码基于 collapse.vue 与 vertical.vue 的结构扩展而来template el-radio-group v-modelisCollapse stylemargin-bottom: 20px el-radio-button :valuefalseexpand/el-radio-button el-radio-button :valuetruecollapse/el-radio-button /el-radio-group el-menu router :default-active$route.path :collapseisCollapse unique-opened selecthandleSelect el-sub-menu index/dashboard template #title el-iconlocation //el-icon spanDashboard/span /template el-menu-item index/dashboard/overviewOverview/el-menu-item el-menu-item index/dashboard/analyticsAnalytics/el-menu-item /el-sub-menu el-menu-item index/orders el-iconicon-menu //el-icon template #titleOrders/template /el-menu-item /el-menu /template script langts setup import { ref } from vue const isCollapse ref(true) const handleSelect (key: string, keyPath: string[]) { console.log(key, keyPath) } /script这里的index直接使用路由 pathrouter模式会自动执行跳转同时default-active绑定$route.path保证刷新后仍高亮当前页面——这正是官方文档中「If true, index will be used as path to activate the route action. Use withdefault-activeto set the active item on load.」的落地写法。总结Menu 组件围绕「水平/垂直两种模式」与「展开态/折叠态两种形态」展开水平模式依赖ellipsis溢出省略与 Tooltip 浮层垂直模式依赖内联展开、unique-opened互斥与collapse折叠所有布局都建立在index唯一标识与indexPath路径推导之上并通过provide/inject在 Menu 根组件与 SubMenu / Menu-Item 之间共享openedMenus、activeIndex、items等状态见 tokens.ts。配合router模式、分组、图标定制与 Popper 偏移控制Menu 足以覆盖从企业官网顶栏到中后台侧边栏的绝大多数导航场景。相关示例源码可继续阅读 docs/examples/menu 目录完整组件实现见 packages/components/menu组件测试用例见 menu.test.ts。【免费下载链接】element-plus A Vue.js 3 UI Library made by Element team项目地址: https://gitcode.com/GitHub_Trending/el/element-plus创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价