Skip to content

ContextMenu 右键菜单

右键激活的菜单,支持子菜单、复选框和单选项。

名称分类说明类型默认值
maxHeight? 风格菜单最大高度,超出后可滚动number | string
hoverColor? 风格自定义菜单项悬停背景色string
ContextMenuItemdivided? 风格是否显示分割线booleanfalse
disabled? 状态是否禁用右键菜单booleanfalse
ContextMenuItemdisabled? 状态是否禁用booleanfalse
ContextMenuCheckboxItemdisabled? 状态是否禁用booleanfalse
ContextMenuRadioItemdisabled? 状态是否禁用booleanfalse
ContextMenuSubdisabled? 状态是否禁用booleanfalse
hideOnClick? 行为点击菜单项后是否关闭booleantrue
lockScroll? 行为菜单打开时是否锁定页面滚动booleanfalse
↑ / ↓? 行为在菜单项之间移动焦点(跳过禁用项)
Enter / Space? 行为选择当前聚焦的菜单项
? 行为打开子菜单
? 行为关闭子菜单,返回父菜单
Escape? 行为关闭菜单
Home / End? 行为跳到第一个/最后一个可用菜单项
items? 内容菜单项(快捷方式)ContextMenuItemDef[]
ContextMenuItemcommand? 内容指令string | number
ContextMenuItemlabel? 内容显示文本string | VNode
ContextMenuItemicon? 内容图标名称string
ContextMenuItemshortcut? 内容快捷键提示,如 ["Ctrl", "C"]string[]
ContextMenuCheckboxItemmodelValue / v-model? 内容是否选中booleanfalse
ContextMenuCheckboxItemlabel? 内容显示文本string | VNode
ContextMenuRadioGroupmodelValue / v-model? 内容当前选中值string
ContextMenuRadioItemvalue? 内容选项值(必填)string
ContextMenuRadioItemlabel? 内容显示文本string | VNode
ContextMenuSublabel? 内容子菜单触发文本string | VNode
ContextMenuSubicon? 内容图标名称string
ContextMenuSubitems? 内容子菜单项(快捷方式)ContextMenuItemDef[]
command? 事件点击菜单项触发(command: string | number) => void
visible-change? 事件菜单显示/隐藏时触发(visible: boolean) => void
default? 插槽右键触发区域
content? 插槽菜单内容,使用子组件组合
open? 暴露手动打开菜单(event: MouseEvent) => void
close? 暴露关闭菜单() => void

基础用法

右键点击触发区域打开右键菜单。使用 items 属性快速设置。

<template>
  <px-context-menu :items="items" @command="handleCommand">
    <div class="demo-area">
      Right-click here
    </div>
  </px-context-menu>
</template>

<script setup lang="ts">
import { PxMessage } from 'sakana-element';

const items = [
  { label: 'Cut', command: 'cut' },
  { label: 'Copy', command: 'copy' },
  { label: 'Paste', command: 'paste' },
  { label: 'Delete', command: 'delete', divided: true },
];

const handleCommand = (command: string) => {
  PxMessage.info(`Command: ${command}`);
};
</script>

<style scoped>
.demo-area {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 100%;
  min-height: 120px;
  border: 2px dashed var(--px-border-color);
  font-family: var(--px-font-family);
  color: var(--px-text-color-secondary);
}
</style>

插槽组合

content 插槽中使用子组件进行完全控制:标签、分隔线、图标和快捷键。

<template>
  <px-context-menu @command="handleCommand">
    <div class="demo-area">
      Right-click for slot-based menu
    </div>
    <template #content>
      <px-context-menu-label>Edit</px-context-menu-label>
      <px-context-menu-item label="Undo" command="undo" :shortcut="['Ctrl', 'Z']" />
      <px-context-menu-item label="Redo" command="redo" :shortcut="['Ctrl', 'Y']" />
      <px-context-menu-separator />
      <px-context-menu-item label="Cut" command="cut" icon="cut" :shortcut="['Ctrl', 'X']" />
      <px-context-menu-item label="Copy" command="copy" icon="clipboard" :shortcut="['Ctrl', 'C']" />
      <px-context-menu-item label="Paste" command="paste" :shortcut="['Ctrl', 'V']" />
    </template>
  </px-context-menu>
</template>

<script setup lang="ts">
import { PxMessage } from 'sakana-element';

const handleCommand = (command: string) => {
  PxMessage.info(`Command: ${command}`);
};
</script>

<style scoped>
.demo-area {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 100%;
  min-height: 120px;
  border: 2px dashed var(--px-border-color);
  font-family: var(--px-font-family);
  color: var(--px-text-color-secondary);
}
</style>

子菜单

使用 PxContextMenuSub 嵌套菜单。子菜单会在悬停时延迟打开。

<template>
  <px-context-menu @command="handleCommand">
    <div class="demo-area">
      Right-click for submenu
    </div>
    <template #content>
      <px-context-menu-item label="Back" command="back" />
      <px-context-menu-item label="Forward" command="forward" />
      <px-context-menu-item label="Reload" command="reload" :shortcut="['Ctrl', 'R']" />
      <px-context-menu-separator />
      <px-context-menu-sub label="More Tools">
        <px-context-menu-item label="Save Page As..." command="save" :shortcut="['Ctrl', 'S']" />
        <px-context-menu-item label="Create Shortcut" command="shortcut" />
        <px-context-menu-item label="Developer Tools" command="devtools" :shortcut="['F12']" />
      </px-context-menu-sub>
    </template>
  </px-context-menu>
</template>

<script setup lang="ts">
import { PxMessage } from 'sakana-element';

const handleCommand = (command: string) => {
  PxMessage.info(`Command: ${command}`);
};
</script>

<style scoped>
.demo-area {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 100%;
  min-height: 120px;
  border: 2px dashed var(--px-border-color);
  font-family: var(--px-font-family);
  color: var(--px-text-color-secondary);
}
</style>

禁用项

在单个菜单项上设置 disabled 以阻止交互。

<template>
  <px-context-menu @command="handleCommand">
    <div class="demo-area">
      Right-click — some items disabled
    </div>
    <template #content>
      <px-context-menu-item label="Cut" command="cut" />
      <px-context-menu-item label="Copy" command="copy" />
      <px-context-menu-item label="Paste" command="paste" disabled />
      <px-context-menu-item label="Delete" command="delete" disabled />
    </template>
  </px-context-menu>
</template>

<script setup lang="ts">
import { PxMessage } from 'sakana-element';

const handleCommand = (command: string) => {
  PxMessage.info(`Command: ${command}`);
};
</script>

<style scoped>
.demo-area {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 100%;
  min-height: 120px;
  border: 2px dashed var(--px-border-color);
  font-family: var(--px-font-family);
  color: var(--px-text-color-secondary);
}
</style>

复选项

使用 PxContextMenuCheckboxItem 配合 v-model 实现切换项。设置 hide-on-clickfalse 保持菜单打开。

<template>
  <px-context-menu :hide-on-click="false">
    <div class="demo-area">
      Right-click for checkbox items
    </div>
    <template #content>
      <px-context-menu-label>View</px-context-menu-label>
      <px-context-menu-checkbox-item v-model="showToolbar" label="Toolbar" />
      <px-context-menu-checkbox-item v-model="showStatusBar" label="Status Bar" />
      <px-context-menu-checkbox-item v-model="showMinimap" label="Minimap" />
    </template>
  </px-context-menu>
</template>

<script setup lang="ts">
import { ref } from 'vue';

const showToolbar = ref(true);
const showStatusBar = ref(true);
const showMinimap = ref(false);
</script>

<style scoped>
.demo-area {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 100%;
  min-height: 120px;
  border: 2px dashed var(--px-border-color);
  font-family: var(--px-font-family);
  color: var(--px-text-color-secondary);
}
</style>

单选项

PxContextMenuRadioItem 包裹在 PxContextMenuRadioGroup 中,配合 v-model 实现互斥选择。

<template>
  <px-context-menu :hide-on-click="false">
    <div class="demo-area">
      Right-click for radio items
    </div>
    <template #content>
      <px-context-menu-label>Theme</px-context-menu-label>
      <px-context-menu-radio-group v-model="theme">
        <px-context-menu-radio-item label="Light" value="light" />
        <px-context-menu-radio-item label="Dark" value="dark" />
        <px-context-menu-radio-item label="System" value="system" />
      </px-context-menu-radio-group>
    </template>
  </px-context-menu>
</template>

<script setup lang="ts">
import { ref } from 'vue';

const theme = ref('light');
</script>

<style scoped>
.demo-area {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 100%;
  min-height: 120px;
  border: 2px dashed var(--px-border-color);
  font-family: var(--px-font-family);
  color: var(--px-text-color-secondary);
}
</style>