在ERP或后天管理系统开发中,右键菜单是提升操作效率的常用交互方式。Vxe UI 提供的 vxe-context-menu 组件,让你可以轻松为任何元素绑定自定义右键菜单,并支持多级菜单、图标配置、禁用/显示控制等丰富功能。本文将从基础用法到高级配置,全面介绍该组件的使用技巧。

菜单配置
通过 options 配置菜单选项,通过 children 最多支持二级菜单

html
<template>
<div>
<vxe-button @contextmenu="showMenuEvent">右键显示</vxe-button>
<vxe-context-menu v-model="showMenu" v-bind="menuOptions" v-on="menuEvents"></vxe-context-menu>
</div>
</template>
<script setup>
import { reactive, ref } from 'vue'
import { VxeUI } from 'vxe-pc-ui'
const showMenu = ref(false)
const menuOptions = reactive({
x: 0,
y: 0,
options: [
[
{ code: '11', name: '新增' },
{ code: '22', name: '删除' },
{
code: '33',
name: '审批',
children: [
{ code: '44', name: '通过' },
{ code: '55', name: '不通过' }
]
},
{ code: '66', name: '查看' }
],
[
{
code: '111',
name: '更多操作',
children: [
{ code: '113', name: '编辑' },
{ code: '114', name: '取消' }
]
},
{ code: '110', name: '驳回' }
]
]
})
const menuEvents = {
optionClick({ option }) {
VxeUI.modal.message({
content: `点击了 ${option.code}`,
status: 'success'
})
}
}
const showMenuEvent = ({ $event }) => {
$event.preventDefault()
$event.stopPropagation()
menuOptions.x = $event.clientX
menuOptions.y = $event.clientY
showMenu.value = true
}
</script>
- 每个菜单项支持以下属性:
| 属性 | 类型 | 说明 |
|---|---|---|
| code | string | number |
| name | string | 菜单项显示文字 |
| children | Array | 子菜单项(支持二级菜单) |
| prefixIcon | string | 前缀图标类名 |
| suffixIcon | string | 后缀图标类名 |
| prefixConfig | object | 前缀配置(支持文字或图标) |
| suffixConfig | object | 后缀配置(支持文字或图标) |
| disabled | boolean | 是否禁用 |
| visible | boolean | 是否显示 |
前缀与后缀图标
通过 prefixIcon / suffixIcon 配置图标,或使用 prefixConfig / suffixConfig 配置自定义内容:

html
<template>
<div>
<vxe-button @contextmenu="showMenuEvent">右键显示</vxe-button>
<vxe-context-menu v-model="showMenu" v-bind="menuOptions"></vxe-context-menu>
</div>
</template>
<script setup>
import { reactive, ref } from 'vue'
const showMenu = ref(false)
const menuOptions = reactive({
x: 0,
y: 0,
options: [
[
{ code: '11', name: '新增', prefixIcon: 'vxe-icon-add' },
{ code: '22', name: '删除', prefixIcon: 'vxe-icon-delete' },
{
code: '33',
name: '审批',
prefixIcon: 'vxe-icon-empty',
children: [
{ code: '44', name: '通过', prefixConfig: { content: 'Ctrl+R' } },
{ code: '55', name: '不通过', prefixConfig: { content: 'Ctrl+X' } }
]
},
{ code: '66', name: '查看', prefixIcon: 'vxe-icon-link' }
],
[
{
code: '111',
name: '更多操作',
children: [
{ code: '113', name: '编辑', prefixConfig: { content: 'Ctrl+V' } },
{ code: '114', name: '取消', prefixConfig: { content: 'Ctrl+C' } }
]
},
{ code: '110', name: '驳回', prefixIcon: 'vxe-icon-add' }
]
]
})
const showMenuEvent = ({ $event }) => {
$event.preventDefault()
$event.stopPropagation()
menuOptions.x = $event.clientX
menuOptions.y = $event.clientY
showMenu.value = true
}
</script>
是否禁用
设置 disabled: true 可让菜单项不可点击,并显示灰色样式:

html
<template>
<div>
<vxe-button @contextmenu="showMenuEvent">右键显示</vxe-button>
<vxe-context-menu v-model="showMenu" v-bind="menuOptions" v-on="menuEvents"></vxe-context-menu>
</div>
</template>
<script setup>
import { reactive, ref } from 'vue'
import { VxeUI } from 'vxe-pc-ui'
const showMenu = ref(false)
const menuOptions = reactive({
x: 0,
y: 0,
options: [
[
{ code: '11', name: '新增(Ctrl+V)', disabled: false },
{ code: '22', name: '删除(Ctrl+T)', prefixIcon: 'vxe-icon-delete', disabled: true },
{
code: '33',
name: '审批',
disabled: false,
children: [
{ code: '44', name: '通过', prefixIcon: 'vxe-icon-check', disabled: false },
{ code: '55', name: '不通过', prefixIcon: 'vxe-icon-close', disabled: false }
]
},
{ code: '66', name: '查看(Ctrl+X)', prefixIcon: 'vxe-icon-link', disabled: true }
],
[
{
code: '111',
name: '更多操作',
disabled: false,
children: [
{ code: '113', name: '编辑(Ctrl+Y)', disabled: true },
{ code: '114', name: '取消(Ctrl+B)', disabled: false }
]
},
{ code: '110', name: '驳回(Ctrl+Z)', disabled: true }
]
]
})
const menuEvents = {
optionClick({ option }) {
VxeUI.modal.message({
content: `点击了 ${option.code}`,
status: 'success'
})
}
}
const showMenuEvent = ({ $event }) => {
$event.preventDefault()
$event.stopPropagation()
menuOptions.x = $event.clientX
menuOptions.y = $event.clientY
showMenu.value = true
}
</script>
是否显示
通过 visible 属性可以动态控制菜单项的显隐,适用于权限控制等场景:

html
<template>
<div>
<vxe-button @contextmenu="showMenuEvent">右键显示</vxe-button>
<vxe-context-menu v-model="showMenu" v-bind="menuOptions" v-on="menuEvents"></vxe-context-menu>
</div>
</template>
<script setup>
import { reactive, ref } from 'vue'
import { VxeUI } from 'vxe-pc-ui'
const showMenu = ref(false)
const menuOptions = reactive({
x: 0,
y: 0,
options: [
[
{ code: '11', name: '新增(Ctrl+V)', visible: true },
{ code: '22', name: '删除(Ctrl+T)', prefixIcon: 'vxe-icon-delete', visible: false },
{
code: '33',
name: '审批',
visible: true,
children: [
{ code: '44', name: '通过', prefixIcon: 'vxe-icon-check', visible: true },
{ code: '55', name: '不通过', prefixIcon: 'vxe-icon-close', visible: true }
]
},
{ code: '66', name: '查看(Ctrl+X)', prefixIcon: 'vxe-icon-link', visible: false }
],
[
{
code: '111',
name: '更多操作',
visible: true,
children: [
{ code: '113', name: '编辑(Ctrl+Y)', visible: false },
{ code: '114', name: '取消(Ctrl+B)', visible: true }
]
},
{ code: '110', name: '驳回(Ctrl+Z)', visible: false }
]
]
})
const menuEvents = {
optionClick({ option }) {
VxeUI.modal.message({
content: `点击了 ${option.code}`,
status: 'success'
})
}
}
const showMenuEvent = ({ $event }) => {
$event.preventDefault()
$event.stopPropagation()
menuOptions.x = $event.clientX
menuOptions.y = $event.clientY
showMenu.value = true
}
</script>
全局调用
除了通过组件方式使用,Vxe UI 还提供了全局 API,方便在任意位置调用:
javascripy
import { VxeUI } from 'vxe-pc-ui'
// 打开右键菜单(指定位置)
VxeUI.contextMenu.open({
x: 100,
y: 200,
options: [
[
{ code: '1', name: '选项一' },
{ code: '2', name: '选项二' }
]
]
})
// 基于鼠标事件打开(自动获取位置)
VxeUI.contextMenu.openByEvent(event, {
options: [
[
{ code: '1', name: '选项一' }
]
]
})
// 关闭右键菜单
VxeUI.contextMenu.close()
事件列表
| 事件名 | 参数 | 说明 |
|---|---|---|
| optionClick | { option, $event } | 点击菜单项时触发 |
| open | { options } | 菜单打开时触发 |
| close | --- | 菜单关闭时触发 |
| show | --- | 菜单显示时触发 |
| hide | --- | 菜单隐藏时触发 |
无论是为表格、树形控件,还是任意 DOM 元素绑定右键菜单,vxe-context-menu 都能提供优雅的右键菜单解决方案。