ContextMenu 右键菜单
右键激活的菜单,支持子菜单、复选框和单选项。
?
| 名称 | 分类 | 说明 | 类型 | 默认值 |
|---|---|---|---|---|
maxHeight | ? 风格 | 菜单最大高度,超出后可滚动 | number | string | — |
hoverColor | ? 风格 | 自定义菜单项悬停背景色 | string | — |
ContextMenuItemdivided | ? 风格 | 是否显示分割线 | boolean | false |
disabled | ? 状态 | 是否禁用右键菜单 | boolean | false |
ContextMenuItemdisabled | ? 状态 | 是否禁用 | boolean | false |
ContextMenuCheckboxItemdisabled | ? 状态 | 是否禁用 | boolean | false |
ContextMenuRadioItemdisabled | ? 状态 | 是否禁用 | boolean | false |
ContextMenuSubdisabled | ? 状态 | 是否禁用 | boolean | false |
hideOnClick | ? 行为 | 点击菜单项后是否关闭 | boolean | true |
lockScroll | ? 行为 | 菜单打开时是否锁定页面滚动 | boolean | false |
↑ / ↓ | ? 行为 | 在菜单项之间移动焦点(跳过禁用项) | — | |
Enter / Space | ? 行为 | 选择当前聚焦的菜单项 | — | |
→ | ? 行为 | 打开子菜单 | — | |
← | ? 行为 | 关闭子菜单,返回父菜单 | — | |
Escape | ? 行为 | 关闭菜单 | — | |
Home / End | ? 行为 | 跳到第一个/最后一个可用菜单项 | — | |
items | ? 内容 | 菜单项(快捷方式) | ContextMenuItemDef[] | — |
ContextMenuItemcommand | ? 内容 | 指令 | string | number | — |
ContextMenuItemlabel | ? 内容 | 显示文本 | string | VNode | — |
ContextMenuItemicon | ? 内容 | 图标名称 | string | — |
ContextMenuItemshortcut | ? 内容 | 快捷键提示,如 ["Ctrl", "C"] | string[] | — |
ContextMenuCheckboxItemmodelValue / v-model | ? 内容 | 是否选中 | boolean | false |
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-click 为 false 保持菜单打开。
<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>