Contextmenu 右键菜单
安装 Avue 后,通过 v-contextmenu 将右键目标关联到一个现有菜单元素。菜单的业务动作由点击事件实现。
效果预览可直接操作下方示例
在任意成员上单击鼠标右键,再选择「查看成员」;下方展示当前成员及菜单关闭原因。也可以用方向键选择、Enter 执行、Esc 关闭。
正在加载示例…
<template>
<div class="contextmenu-demo">
<p class="contextmenu-demo__hint">右键点击成员打开菜单;打开后用 ↑ / ↓ 选择、Enter 执行、Esc 关闭。手机上可直接点击“查看”。</p>
<ul class="contextmenu-demo__members">
<li v-for="item in list"
:key="item.id"
v-contextmenu="{ id: menuId, value: item, event: handleOpen, hide: handleHide }"
class="contextmenu-demo__member">
<div>
<strong>{{ item.name }}</strong>
<span>{{ item.department }} · {{ item.id }}</span>
</div>
<el-tag v-if="item.followed" size="small">已关注</el-tag>
<el-button link type="primary" @click="viewMember(item)">查看</el-button>
</li>
</ul>
<ul :id="menuId"
class="el-dropdown-menu el-popper contextmenu-demo__menu"
aria-label="成员操作"
style="display: none">
<li class="el-dropdown-menu__item" @click="viewMember(activeMember)">查看成员</li>
<li class="el-dropdown-menu__item" @click="toggleFollow">
{{ activeMember?.followed ? '取消关注' : '关注成员' }}
</li>
</ul>
<div class="contextmenu-demo__result" role="status" aria-live="polite">
<p>菜单状态:{{ menuOpen ? `已打开,当前成员 ${activeMember.name}` : '已关闭' }}</p>
<p>最近关闭:{{ lastClosed }}</p>
<p>操作结果:{{ result }}</p>
</div>
</div>
</template>
<script setup>
import { onBeforeUnmount, ref, useId } from 'vue'
const menuId = `member-menu-${useId()}`
const list = ref([
{ id: 'M001', name: '张三', department: '研发部', followed: false },
{ id: 'M002', name: '李四', department: '产品部', followed: false },
{ id: 'M003', name: '王五', department: '设计部', followed: false }
])
const activeMember = ref(null)
const menuOpen = ref(false)
const lastClosed = ref('尚未打开过菜单')
const result = ref('选择“查看成员”或“关注成员”后,这里显示本地操作结果。')
const closeReasons = {
outside: '点击菜单外部',
escape: '按下 Esc',
select: '选中菜单项',
switch: '切换右键目标',
unmount: '目标卸载',
close: '主动关闭'
}
let active = true
function handleOpen(row, show) {
activeMember.value = row
show()
menuOpen.value = true
}
function handleHide(row, mouseEvent, reason) {
if (!active) return
menuOpen.value = false
lastClosed.value = `${row.name}:${closeReasons[reason] || '关闭菜单'}(${reason})`
}
function viewMember(row) {
if (!row) return
result.value = `${row.id} / ${row.name} / ${row.department} / ${row.followed ? '已关注' : '未关注'}`
}
function toggleFollow() {
const row = activeMember.value
if (!row) return
row.followed = !row.followed
result.value = `${row.name}已${row.followed ? '关注' : '取消关注'},成员列表已同步更新。`
}
onBeforeUnmount(() => {
active = false
})
</script>
<style scoped>
.contextmenu-demo__hint {
color: var(--el-text-color-secondary);
line-height: 1.7;
}
.contextmenu-demo__members {
display: grid;
gap: 10px;
margin: 12px 0;
padding: 0;
list-style: none;
}
.contextmenu-demo__member {
display: flex;
align-items: center;
gap: 12px;
padding: 12px 16px;
border: 1px solid var(--el-border-color-lighter);
border-radius: 8px;
background: var(--el-fill-color-light);
}
.contextmenu-demo__member > div {
flex: 1;
min-width: 0;
}
.contextmenu-demo__member > div > strong,
.contextmenu-demo__member > div > span {
display: block;
overflow-wrap: anywhere;
}
.contextmenu-demo__member > div > span {
margin-top: 4px;
color: var(--el-text-color-secondary);
font-size: 13px;
}
.contextmenu-demo__menu {
min-width: 150px;
margin: 0;
padding: 6px 0;
list-style: none;
}
.contextmenu-demo__menu > li:focus-visible {
outline: 2px solid var(--el-color-primary);
outline-offset: -2px;
background: var(--el-color-primary-light-9);
}
.contextmenu-demo__result {
padding: 8px 14px;
border-radius: 8px;
background: var(--el-fill-color-lighter);
overflow-wrap: anywhere;
}
.contextmenu-demo__result p {
margin: 6px 0;
}
</style>
| 指令配置 | 类型 | 说明 |
|---|---|---|
id | string | 菜单元素 id,不带 #,每个示例使用唯一 id |
value | any | 当前记录,传给显示和隐藏回调 |
disabled | boolean | true 时保留浏览器原生右键行为 |
event(value, show, mouseEvent) | function | 自定义打开逻辑;必须调用 show() 才会显示,返回 false 可取消 |
hide(value, mouseEvent, reason) | function | 关闭通知;reason 为 outside / escape / select / switch / unmount 等 |
没有配置 event 时自动显示菜单。点击外部、按 Esc 或选中菜单项会隐藏,切换目标会先关闭上一个菜单。菜单根节点建议使用 ul,直接子菜单项使用 li;嵌套 ul/ol 会作为子菜单处理,data-contextmenu-keep-open 可阻止某个菜单项点击后自动关闭。
这是鼠标右键入口,手机业务应额外提供可见操作按钮。菜单卸载时指令会清理事件监听。
