AvueAvue
首页
  • 开发指南
  • Skill开发
  • 在线测试工具
  • Form组件
  • Crud组件
  • Default组件
  • Data组件
  • Component组件
产品
工作台
授权
联系
2.x文档
个人支付接口
首页
  • 开发指南
  • Skill开发
  • 在线测试工具
  • Form组件
  • Crud组件
  • Default组件
  • Data组件
  • Component组件
产品
工作台
授权
联系
2.x文档
个人支付接口
  • Article 文章
  • Group 分组容器
  • Title 标题文本
  • CountUp 数字动画
  • Comment 评论
  • Chat 客服聊天
  • Captcha 验证码
  • Contextmenu 右键菜单
  • Clipboard 复制文本
  • DialogForm 弹窗表单
  • Draggable 拖拽
  • Export Excel 导入与导出
  • Flow 流程
  • FilterBuilder 高级筛选
  • FileManager 文件管理
  • QRCode 二维码
  • Iframe 嵌入页面
  • ImagePreview 图片预览
  • Login 登录组件
  • License 授权书
  • Print 打印
  • Screenshot 页面截图
  • Search 标签搜索
  • Sign 电子签名
  • TextEllipsis 超出文本省略
  • Tabs 选项卡
  • Tree 树型
  • Video 摄像头
  • Calendar 日历组合示例

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>
指令配置类型说明
idstring菜单元素 id,不带 #,每个示例使用唯一 id
valueany当前记录,传给显示和隐藏回调
disabledbooleantrue 时保留浏览器原生右键行为
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 可阻止某个菜单项点击后自动关闭。

这是鼠标右键入口,手机业务应额外提供可见操作按钮。菜单卸载时指令会清理事件监听。

最后更新:
贡献者: smallwei
Prev
Captcha 验证码
Next
Clipboard 复制文本