ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

Element Plus Dropdown 下拉菜单组件完全指南:从基础用法到虚拟触发与源码剖析

Element Plus Dropdown 下拉菜单组件完全指南:从基础用法到虚拟触发与源码剖析 Element Plus Dropdown 下拉菜单组件完全指南从基础用法到虚拟触发与源码剖析【免费下载链接】element-plus A Vue.js 3 UI Library made by Element team项目地址: https://gitcode.com/GitHub_Trending/el/element-plus本文是 Element PlusVue 3 组件库中Dropdown下拉菜单组件的完整实战指南。你将掌握如何通过默认插槽与dropdown插槽组织触发元素与菜单内容、通过trigger控制悬停/点击/右键触发、借助split-button与command事件构建可交互的操作菜单并深入理解hide-on-click、placement、虚拟触发等高级能力背后的源码实现。文中所有配置示例均取自仓库真实文档与源码可直接复制到你的 Vue 3 项目中运行。组件定位与基本结构Dropdown是 Element Plus 中用于展示链接与操作列表的可切换菜单组件。它由两个核心部分组成触发元素Trigger与下拉面板Menu。组件源码位于 packages/components/dropdown整体基于 Tooltip 与 Popper 能力构建——从 dropdown.ts 可以看到其 props 大量复用useTooltipTriggerProps、useTooltipContentProps以及 popper 的roleTypes因此你在 Tooltip 上学到的定位、主题、teleport 等概念在这里同样适用。在模板结构上Dropdown提供两个插槽详见下文API 参考default插槽渲染触发元素必须是合法的 DOM 元素如span、button或el-组件以便绑定触发监听器dropdown插槽渲染下拉菜单内容通常是一个el-dropdown-menu元素内部再放置若干el-dropdown-item。基础用法悬停展开操作菜单默认情况下将鼠标悬停在触发元素上即可展开菜单无需点击。触发元素由default插槽渲染下拉部分由dropdown插槽渲染。对应示例见 basic-usage.vuetemplate el-dropdown span classel-dropdown-link Dropdown List el-icon classel-icon--right arrow-down / /el-icon /span template #dropdown el-dropdown-menu el-dropdown-itemAction 1/el-dropdown-item el-dropdown-itemAction 2/el-dropdown-item el-dropdown-itemAction 3/el-dropdown-item el-dropdown-item disabledAction 4/el-dropdown-item el-dropdown-item dividedAction 5/el-dropdown-item /el-dropdown-menu /template /el-dropdown /template script langts setup import { ArrowDown } from element-plus/icons-vue /script这里同时演示了两个重要细节disabled属性使菜单项变为禁用态不可点击、不触发命令事件divided属性为该菜单项上方渲染一条分隔线。从 dropdownItemProps 的源码可见disabled与divided均为Boolean类型、默认false而command支持Object | String | Number三种取值默认值为{}。Placement六种弹出方位通过placement属性可以控制菜单的弹出位置官方文档说明支持 6 种取值top、top-start、top-end、bottom、bottom-start、bottom-end默认值为bottom。示例见 placements.vueel-dropdown placementtop-start el-button topStart /el-button template #dropdown el-dropdown-menu el-dropdown-itemThe Action 1st/el-dropdown-item el-dropdown-itemThe Action 2nd/el-dropdown-item el-dropdown-itemThe Action 3rd/el-dropdown-item /el-dropdown-menu /template /el-dropdown !-- 依次类推top / top-end / bottom-start / bottom / bottom-end --在 dropdown.ts 中placement的类型定义为Placement来自element-plus/components/popper默认bottom。-start与-end后缀用于控制菜单与触发元素边缘的对齐方向例如bottom-start表示菜单底部左对齐bottom-end表示底部右对齐适合右侧空间不足的页面布局。触发元素普通触发与 split-button 拆分按钮触发元素可以是任意内容最常用的是按钮。若希望将触发按钮拆分为左侧常规按钮 右侧触发箭头的按钮组形态可设置split-button属性。文档示例见 triggering-element.vueel-dropdown split-button typeprimary clickhandleClick Dropdown List template #dropdown el-dropdown-menu el-dropdown-itemAction 1/el-dropdown-item el-dropdown-itemAction 2/el-dropdown-item el-dropdown-itemAction 3/el-dropdown-item el-dropdown-item dividedAction 4/el-dropdown-item el-dropdown-itemAction 5/el-dropdown-item /el-dropdown-menu /template /el-dropdown在拆分按钮模式下左侧按钮的点击会触发click事件参数为MouseEvent右侧箭头区域才是真正的菜单触发目标。文档中还特别说明如果想在第三个与第四个菜单项之间插入分隔线只需为第四个菜单项添加divided属性即可如上方示例中Action 4所示。与之配套的属性还包括type菜单按钮的类型取值与Button组件一致default/primary/success/warning/info/danger以及已废弃的text仅在split-button为true时生效button-props传递给内部按钮组件的 props参考 Button 组件的 Attributes类型为PartialButtonPropssize菜单尺寸同时作用于拆分按钮取值为 | large | default | small。触发方式hover / click / contextmenu默认触发方式为hover悬停可以通过trigger属性改为click点击或contextmenu右键也支持传入数组组合多种触发方式Arrayclick | hover | contextmenu。文档示例 how-to-trigger.vue 同时展示了三种方式el-dropdown triggerclick !-- 点击触发 -- /el-dropdown el-dropdown triggercontextmenu !-- 右键触发 -- /el-dropdown该示例中的菜单项还使用了:iconPlus、:iconCirclePlusFilled等属性为每个菜单项配置图标图标来源为element-plus/icons-vue。从源码看trigger的类型定义复用了 Tooltip 的触发属性并显式排除了focus触发类型dropdown.ts。此外键盘也是可用的触发途径trigger-keys属性自 2.9.1 起用于指定按下哪些按键时可触发菜单默认值为[Enter, Space, ArrowDown, NumpadEnter]对应源码中的EVENT_CODE.enter、EVENT_CODE.space、EVENT_CODE.down、EVENT_CODE.numpadEnter见 dropdown.ts。悬停触发模式下还有两个与延迟相关的属性show-timeout展开前的延迟毫秒数默认150hide-timeout收起前的延迟毫秒数默认150。源码中二者的默认值均为150dropdown.ts适度的延迟可避免鼠标在触发元素与菜单之间移动时菜单频繁闪烁。菜单隐藏行为hide-on-click默认情况下点击菜单项后菜单会自动收起。若希望点击菜单项后菜单保持展开例如需要连续选择多项可设置hide-on-click为false。示例见 menu-hiding-behavior.vueel-dropdown :hide-on-clickfalse span classel-dropdown-link Dropdown Listel-icon classel-icon--rightarrow-down //el-icon /span template #dropdown el-dropdown-menu el-dropdown-itemAction 1/el-dropdown-item el-dropdown-itemAction 2/el-dropdown-item el-dropdown-item disabledAction 4/el-dropdown-item el-dropdown-item dividedAction 5/el-dropdown-item el-dropdown-item dividedAction 6/el-dropdown-item /el-dropdown-menu /template /el-dropdown该属性的默认值为true类型为Boolean对应源码 dropdown.ts。组件内部通过IElDropdownInstance接口暴露的hideOnClick计算属性instance.ts在点击菜单项时决定是否调用隐藏逻辑。Command 事件菜单项与回调的桥梁点击每个菜单项时会触发command事件事件参数即每个菜单项通过command属性设定的值。这是 Dropdown 最核心的交互模式菜单项无需各自绑定点击事件只需在Dropdown上统一监听command。示例见 command-event.vuetemplate el-dropdown commandhandleCommand span classel-dropdown-link Dropdown Listel-icon classel-icon--rightarrow-down //el-icon /span template #dropdown el-dropdown-menu el-dropdown-item commandaAction 1/el-dropdown-item el-dropdown-item commandbAction 2/el-dropdown-item el-dropdown-item commandcAction 3/el-dropdown-item el-dropdown-item commandd disabledAction 4/el-dropdown-item el-dropdown-item commande dividedAction 5/el-dropdown-item /el-dropdown-menu /template /el-dropdown /template script langts setup import { ElMessage } from element-plus import { ArrowDown } from element-plus/icons-vue const handleCommand (command: string | number | object) { ElMessage(click on item ${command}) } /scriptcommand事件的处理函数签名为(...args: any[]) void参数就是被点击菜单项通过command属性派发的值。由于command支持string | number | object类型你可以用对象携带结构化数据如{ id: 1, action: delete }再在回调中按需解析。手动控制handleOpen / handleClose除了交互触发你还可以通过组件实例手动调用handleOpen或handleClose来打开/关闭下拉菜单。文档示例 dropdown-methods.vue 展示了利用visible-change事件实现同时只能展开一个菜单的互斥逻辑script setup langts import { ref } from vue import type { DropdownInstance } from element-plus const dropdown1 refDropdownInstance() function handleVisible2(visible: any) { if (!dropdown1.value) return if (visible) { dropdown1.value.handleClose() } else { dropdown1.value.handleOpen() } } function showClick() { if (!dropdown1.value) return dropdown1.value.handleOpen() } /script template el-button clickshowClickshow/el-button el-dropdown refdropdown1 triggercontextmenu stylemargin-right: 30px !-- Dropdown List1 -- /el-dropdown el-dropdown triggercontextmenu visible-changehandleVisible2 !-- Dropdown List2 -- /el-dropdown /template其中DropdownInstance类型导出自 Element Plus 包组件导出入口。visible-change事件在菜单出现/消失时触发参数true表示出现、false表示消失。示例的逻辑是当第二个下拉展开时关闭第一个visible为true时调用handleClose当第二个收起时重新打开第一个从而保证任意时刻只有一个菜单处于展开状态。尺寸large / default / smallDropdown 在默认尺寸之外额外提供large、default、small三种尺寸通过size属性设置并且该尺寸同样作用于split-button拆分按钮。示例见 sizes.vueel-dropdown sizelarge split-button typeprimaryLarge/el-dropdown el-dropdown split-button typeprimaryDefault/el-dropdown el-dropdown sizesmall split-button typeprimarySmall/el-dropdownsize的默认值为即跟随全局组件尺寸配置可通过 ConfigProvider 统一控制类型为 | large | default | small源码见 dropdown.ts。虚拟触发让菜单挂载到任意元素2.11.3自 2.11.3 起Dropdown 支持虚拟触发Virtual triggering当你不希望菜单由组件内部元素触发而是想把它渲染到其他任意元素上时可以将触发与内容分离。文档示例 virtual-trigger.vue 实现了一个自定义的右键菜单template el-card classcontent body-classcard-body clickhandleClick contextmenuhandleContextmenu Right click /el-card el-dropdown refdropdownRef :virtual-reftriggerRef :show-arrowfalse :popper-options{ modifiers: [{ name: offset, options: { offset: [0, 0] } }], } virtual-triggering triggercontextmenu placementbottom-start template #dropdown el-dropdown-menu el-dropdown-item :iconPlusAction 1/el-dropdown-item el-dropdown-item :iconCirclePlusFilled Action 2 /el-dropdown-item el-dropdown-item :iconCirclePlusAction 3/el-dropdown-item el-dropdown-item :iconCheckAction 4/el-dropdown-item el-dropdown-item :iconCircleCheckAction 5/el-dropdown-item /el-dropdown-menu /template /el-dropdown /template script langts setup import { ref } from vue import type { DropdownInstance } from element-plus const dropdownRef refDropdownInstance() const position ref({ top: 0, left: 0, bottom: 0, right: 0 } as DOMRect) // 虚拟引用元素只需实现 getBoundingClientRect const triggerRef ref({ getBoundingClientRect: () position.value, }) const handleClick () { dropdownRef.value?.handleClose() } const handleContextmenu (event: MouseEvent) { const { clientX, clientY } event position.value DOMRect.fromRect({ x: clientX, y: clientY }) event.preventDefault() dropdownRef.value?.handleOpen() } /script实现要点如下virtual-triggering布尔属性开启虚拟触发模式virtual-ref指定菜单所依附的参考元素。这里传入了仅实现getBoundingClientRect方法的对象——position在右键事件中通过DOMRect.fromRect更新为鼠标坐标从而让菜单跟随鼠标位置弹出show-arrow2.11.3控制菜单是否显示箭头本例设为false以呈现原生右键菜单的效果popper-options透传给 popper.js 的参数本例通过offsetmodifier 将偏移设为[0, 0]让菜单紧贴鼠标位置。在源码层面virtualTriggering与virtualRef均直接复用useTooltipTriggerProps对应属性dropdown.tsshowArrow默认值为true同文件 L109-L112与文档 API 表中的—无显式默认值并不冲突——virtual-triggering与virtual-ref需要由使用方按需提供。Dropdown API 参考以下 API 信息直接继承自官方文档 dropdown.md 并对照源码 dropdown.ts 做了核实。Dropdown Attributes名称说明类型默认值type菜单按钮类型参考Button组件仅在split-button为 true 时生效 \| default \| primary \| success \| warning \| info \| danger \| texttext 已废弃size菜单尺寸同时作用于拆分按钮 \| large \| default \| smallbutton-props传给按钮组件的 props参考 Button Attributesobject—max-height菜单的最大高度string / numbersplit-button是否显示按钮组booleanfalsedisabled是否禁用booleanfalseplacement弹出菜单的位置top \| top-start \| top-end \| bottom \| bottom-start \| bottom-endbottomeffectTooltip 主题内置dark/lightdark \| light / stringlighttrigger触发方式click \| hover \| contextmenu / Arrayclick \| hover \| contextmenuhovertrigger-keys2.9.1指定按下哪些按键可触发string[][Enter, Space, ArrowDown, NumpadEnter]virtual-triggering2.11.3是否开启虚拟触发boolean—virtual-ref2.11.3指定菜单所依附的参考元素HTMLElement—hide-on-click点击菜单项后是否隐藏菜单booleantrueshow-arrow2.11.3菜单内容是否显示箭头booleantrueshow-timeout展开前延迟仅hover触发生效number150hide-timeout收起前延迟仅hover触发生效number150role下拉菜单的 ARIA role 属性根据场景可改为navigationdialog \| grid \| group \| listbox \| menu \| navigation \| tooltip \| treemenutabindexDropdown 的 tabindexnumber / string0popper-classDropdown 弹层的自定义类名string / objectpopper-style2.11.5Dropdown 弹层的自定义样式string / object—popper-optionspopper.js 参数object{modifiers: [{name: computeStyles, options: {gpuAcceleration: false}}]}teleported2.2.20弹层是否 teleport 到 bodybooleantrueappend-to2.13.0下拉内容挂载到哪个元素CSSSelector / HTMLElement—persistent2.9.5当下拉处于非激活状态且persistent为false时菜单将被销毁booleantrue关于上述属性的源码佐证popperOptions默认值为{}并接受PartialOptions来自popperjs/coredropdown.tsrole的可选值来自 popper 导出的roleTypes同文件 L156-L160默认menuteleported与appendTo直接复用useTooltipContentProps的同名属性同文件 L167-L171persistent默认true同文件 L175-L178关闭后菜单在不活跃时会被销毁从而释放 DOM 节点。Dropdown Slots名称说明子标签defaultDropdown 的内容。注意必须是合法的 HTML DOM 元素如span、button等或el-组件以便绑定触发监听器—dropdownDropdown 菜单内容通常是一个el-dropdown-menu元素Dropdown-MenuDropdown Events名称说明类型clicksplit-button为true时点击左侧按钮触发(e: MouseEvent) voidcommand点击菜单项时触发参数为菜单项派发的 command(...args: any[]) voidvisible-change菜单出现/消失时触发出现为true消失为false(val: boolean) voidDropdown Exposes方法说明类型handleOpen打开下拉菜单() voidhandleClose关闭下拉菜单() voidDropdown-Menu APIel-dropdown-menu用于承载菜单项集合其组件实现位于 dropdown-menu.vue。Dropdown-Menu Slots名称说明子标签defaultDropdown Menu 的内容Dropdown-ItemDropdown-Item APIel-dropdown-item是单个菜单项内部实际渲染由 dropdown-item.vue 与 dropdown-item-impl.vue 协作完成。Dropdown-Item Attributes名称说明类型默认值command派发给 Dropdowncommand回调的命令值string / number / object—disabled是否禁用该菜单项booleanfalsedivided是否显示分隔线booleanfalseicon自定义图标string / Component—Dropdown-Item Slots名称说明default自定义菜单项内容icon2.13.1自定义图标会覆盖iconprop无障碍与键盘导航Dropdown 在无障碍方面做了内置处理role属性默认值为menu为菜单容器声明 ARIA 语义若你将它用作导航菜单可以改为navigation。在源码 dropdown.ts 中还定义了三组键盘导航按键FIRST_KEYSArrowDown、PageDown、Home——用于将焦点移至第一个菜单项LAST_KEYSArrowUp、PageUp、End——用于将焦点移至最后一个菜单项FIRST_LAST_KEYS以上两者的合集。配合默认的trigger-keysEnter、Space、ArrowDown、NumpadEnter键盘用户可以不依赖鼠标完成聚焦触发元素 → 展开菜单 → 方向键移动 → 回车确认的完整操作链路。相关行为测试覆盖在 dropdown.test.ts 中可作为阅读组件交互细节的补充材料。总结Element Plus 的Dropdown组件以 Tooltip/Popper 为底层基础设施提供了从基础悬停菜单到split-button拆分按钮、从command事件驱动到虚拟触发自定义右键菜单的完整能力矩阵。核心要点回顾结构default插槽放触发元素dropdown插槽放el-dropdown-menuel-dropdown-item触发trigger支持hover默认/click/contextmenu并可组合数组trigger-keys控制键盘触发按键交互hide-on-click控制点击后是否收起command事件统一处理菜单项回调visible-change感知开合状态handleOpen/handleClose支持命令式控制形态placement六方位定位size三种尺寸split-button拆分触发virtual-triggering实现任意元素上的自定义菜单。所有示例源码均可在仓库 docs/examples/dropdown 目录下找到组件实现与完整 API 定义见 packages/components/dropdown可随时对照查阅。【免费下载链接】element-plus A Vue.js 3 UI Library made by Element team项目地址: https://gitcode.com/GitHub_Trending/el/element-plus创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表