目录
- [1. 概述](#1. 概述 "#1-%E6%A6%82%E8%BF%B0")
- [2. Menu 类](#2. Menu 类 "#2-menu-%E7%B1%BB")
- [3. MenuItem 类](#3. MenuItem 类 "#3-menuitem-%E7%B1%BB")
- [4. 菜单类型](#4. 菜单类型 "#4-%E8%8F%9C%E5%8D%95%E7%B1%BB%E5%9E%8B")
- [5. 角色 (Roles)](#5. 角色 (Roles) "#5-%E8%A7%92%E8%89%B2-roles")
- [6. 快捷键 (Accelerator)](#6. 快捷键 (Accelerator) "#6-%E5%BF%AB%E6%8D%B7%E9%94%AE-accelerator")
- [7. 实际应用示例](#7. 实际应用示例 "#7-%E5%AE%9E%E9%99%85%E5%BA%94%E7%94%A8%E7%A4%BA%E4%BE%8B")
- [8. 平台差异](#8. 平台差异 "#8-%E5%B9%B3%E5%8F%B0%E5%B7%AE%E5%BC%82")
1. 概述
css
复制代码
Menu(菜单)
│
├── MenuItem(菜单项)
├── MenuItem(菜单项)
│ │
│ └── Submenu(子菜单)
│ ├── MenuItem
│ └── MenuItem
├── MenuItem(复选框)
└── MenuItem(分隔线)
菜单类型
| 类型 |
说明 |
使用场景 |
| 应用菜单 |
窗口顶部的菜单栏 |
主菜单 |
| 上下文菜单 |
右键点击弹出的菜单 |
操作菜单 |
| 子菜单 |
菜单项的嵌套菜单 |
组织功能 |
2.1 创建菜单
javascript
复制代码
const { Menu, MenuItem } = require('electron')
const menu = new Menu()
2.2 设置应用菜单
javascript
复制代码
const template = [
{
label: '文件',
submenu: [
{ label: '新建', accelerator: 'CmdOrCtrl+N', click: () => {} },
{ type: 'separator' },
{ label: '退出', accelerator: 'CmdOrCtrl+Q', click: () => app.quit() }
]
},
{
label: '编辑',
submenu: [
{ role: 'undo' },
{ role: 'redo' },
{ type: 'separator' },
{ role: 'cut' },
{ role: 'copy' },
{ role: 'paste' }
]
}
]
const menu = Menu.buildFromTemplate(template)
Menu.setApplicationMenu(menu)
2.3 静态方法
| 方法 |
说明 |
Menu.setApplicationMenu(menu) |
设置应用菜单 |
Menu.getApplicationMenu() |
获取应用菜单 |
Menu.buildFromTemplate(template) |
从模板构建菜单 |
Menu.sendActionToFirstResponder(action) |
macOS 专用 |
2.4 实例方法
| 方法 |
说明 |
menu.popup([options]) |
弹出菜单(作为上下文菜单) |
menu.closePopup() |
关闭弹出的菜单 |
menu.append(menuItem) |
追加菜单项 |
menu.insert(pos, menuItem) |
在指定位置插入菜单项 |
menu.getMenuItemById(id) |
根据 ID 获取菜单项 |
javascript
复制代码
menu.popup({
window: BrowserWindow, // 指定窗口,默认聚焦窗口
x: 100, // x 坐标
y: 200, // y 坐标
positioningItem: 0, // macOS:在鼠标位置高亮的项
callback: () => {} // 菜单关闭后的回调
})
2.6 实例事件
| 事件 |
说明 |
menu-will-show |
调用 popup() 时触发 |
menu-will-close |
菜单关闭时触发 |
3.1 基本创建
javascript
复制代码
const { MenuItem } = require('electron')
const item = new MenuItem({
label: '新建文件',
click: () => {
console.log('点击了新建文件')
}
})
3.2 构造函数选项
| 选项 |
类型 |
说明 |
label |
string |
菜单项文本 |
click |
function |
点击回调 |
role |
string |
预定义角色 |
type |
string |
菜单项类型 |
accelerator |
Accelerator |
快捷键 |
icon |
NativeImage/string |
图标 |
enabled |
boolean |
是否启用 |
visible |
boolean |
是否可见 |
checked |
boolean |
是否选中(checkbox/radio) |
submenu |
Menu/MenuItem[] |
子菜单 |
id |
string |
唯一标识 |
before |
string[] |
在某项之前插入 |
after |
string[] |
在某项之后插入 |
3.3 实例属性
| 属性 |
说明 |
可修改 |
id |
唯一标识 |
✅ |
label |
显示文本 |
✅ |
click |
点击函数 |
❌ |
type |
类型 |
❌ |
role |
角色 |
❌ |
accelerator |
快捷键 |
❌ |
icon |
图标 |
✅ |
sublabel |
子标签 (macOS) |
✅ |
toolTip |
提示文本 (macOS) |
✅ |
enabled |
是否启用 |
✅ |
visible |
是否可见 |
✅ |
checked |
是否选中 |
✅ |
submenu |
子菜单 |
❌ |
4. 菜单类型
4.1 普通菜单项
javascript
复制代码
{
label: '新建',
click: () => createNewFile()
}
4.2 分隔线
javascript
复制代码
{ type: 'separator' }
4.3 子菜单
javascript
复制代码
{
label: '文件',
submenu: [
{ label: '新建', click: () => {} },
{ label: '打开', click: () => {} }
]
}
4.4 复选框菜单项
javascript
复制代码
{
label: '自动保存',
type: 'checkbox',
checked: true,
click: (menuItem) => {
console.log('自动保存:', menuItem.checked)
}
}
4.5 单选菜单项
javascript
复制代码
{
label: '简体中文',
type: 'radio',
checked: true,
click: () => setLanguage('zh')
},
{
label: 'English',
type: 'radio',
checked: false,
click: () => setLanguage('en')
}
4.6 动态构建子菜单
javascript
复制代码
{
label: '最近文件',
submenu: [
{ label: 'file1.txt', click: () => openFile('file1.txt') },
{ label: 'file2.txt', click: () => openFile('file2.txt') },
{ type: 'separator' },
{ label: '清除最近文件', role: 'clearRecentDocuments' }
]
}
5. 角色 (Roles)
5.1 通用角色
| 角色 |
说明 |
undo |
撤销 |
redo |
重做 |
cut |
剪切 |
copy |
复制 |
paste |
粘贴 |
delete |
删除 |
selectAll |
全选 |
reload |
重新加载 |
forceReload |
强制重新加载 |
toggleDevTools |
切换开发者工具 |
togglefullscreen |
切换全屏 |
resetZoom |
重置缩放 |
zoomIn |
放大 |
zoomOut |
缩小 |
minimize |
最小化窗口 |
close |
关闭窗口 |
quit |
退出应用 |
5.2 macOS 特有角色
| 角色 |
说明 |
about |
关于面板 |
hide |
隐藏应用 |
hideOthers |
隐藏其他应用 |
unhide |
显示所有应用 |
startSpeaking |
开始朗读 |
stopSpeaking |
停止朗读 |
front |
窗口前置 |
appMenu |
应用菜单 |
fileMenu |
文件菜单 |
editMenu |
编辑菜单 |
viewMenu |
视图菜单 |
windowMenu |
窗口菜单 |
help |
帮助菜单 |
services |
服务菜单 |
shareMenu |
分享菜单 |
5.3 使用角色
javascript
复制代码
{
label: '编辑',
submenu: [
{ role: 'undo', label: '撤销' },
{ role: 'redo', label: '重做' },
{ type: 'separator' },
{ role: 'cut', label: '剪切' },
{ role: 'copy', label: '复制' },
{ role: 'paste', label: '粘贴' }
]
}
⚠️ 注意 :macOS 上使用 role 时,label 和 accelerator 会被忽略,会自动使用系统默认值。
6. 快捷键 (Accelerator)
6.1 基本语法
javascript
复制代码
{
label: '新建',
accelerator: 'CmdOrCtrl+N',
click: () => {}
}
6.2 常用快捷键格式
| 格式 |
说明 |
示例 |
CmdOrCtrl+N |
命令/控制 + N |
Ctrl+N / ⌘N |
Cmd+N |
仅 macOS |
⌘N |
Ctrl+Shift+N |
控制 + Shift + N |
Ctrl+Shift+N |
Alt+F |
Alt + F |
Alt+F |
F5 |
功能键 |
F5 |
6.3 修饰键
| 修饰键 |
Windows/Linux |
macOS |
Ctrl |
✅ |
❌ |
Alt |
✅ |
✅ |
Shift |
✅ |
✅ |
Cmd / Command |
❌ |
✅ |
CmdOrCtrl |
✅ |
✅ (使用 ⌘) |
6.4 快捷键选项
javascript
复制代码
{
label: '粘贴',
accelerator: 'CmdOrCtrl+V',
acceleratorWorksWhenHidden: false, // macOS:隐藏时是否生效
registerAccelerator: true // 是否注册到系统
}
7. 实际应用示例
7.1 应用菜单完整示例
javascript
复制代码
const { app, Menu, MenuItem, BrowserWindow, shell } = require('electron')
function createMenu() {
const template = [
{
label: '文件',
submenu: [
{
label: '新建窗口',
accelerator: 'CmdOrCtrl+N',
click: () => createNewWindow()
},
{
label: '打开文件',
accelerator: 'CmdOrCtrl+O',
click: () => openFile()
},
{
label: '保存',
accelerator: 'CmdOrCtrl+S',
click: () => saveFile()
},
{ type: 'separator' },
{
label: '导出',
submenu: [
{ label: '导出为 PDF', click: () => exportPDF() },
{ label: '导出为 Word', click: () => exportWord() }
]
},
{ type: 'separator' },
{
label: '退出',
accelerator: 'CmdOrCtrl+Q',
click: () => app.quit()
}
]
},
{
label: '编辑',
submenu: [
{ role: 'undo' },
{ role: 'redo' },
{ type: 'separator' },
{ role: 'cut' },
{ role: 'copy' },
{ role: 'paste' },
{ role: 'delete' },
{ type: 'separator' },
{ role: 'selectAll' }
]
},
{
label: '视图',
submenu: [
{ role: 'reload' },
{ role: 'forceReload' },
{ role: 'toggleDevTools' },
{ type: 'separator' },
{ role: 'resetZoom' },
{ role: 'zoomIn' },
{ role: 'zoomOut' },
{ type: 'separator' },
{ role: 'togglefullscreen' }
]
},
{
label: '窗口',
submenu: [
{ role: 'minimize' },
{ role: 'zoom' },
{ role: 'close' }
]
},
{
label: '帮助',
submenu: [
{
label: '关于',
click: () => showAboutDialog()
},
{
label: '文档',
click: () => shell.openExternal('https://electronjs.org')
}
]
}
]
const menu = Menu.buildFromTemplate(template)
Menu.setApplicationMenu(menu)
}
7.2 自定义上下文菜单
javascript
复制代码
const { Menu } = require('electron')
function showContextMenu(window) {
const contextMenu = Menu.buildFromTemplate([
{
label: '复制',
accelerator: 'CmdOrCtrl+C',
role: 'copy'
},
{
label: '粘贴',
accelerator: 'CmdOrCtrl+V',
role: 'paste'
},
{ type: 'separator' },
{
label: '全选',
accelerator: 'CmdOrCtrl+A',
role: 'selectAll'
},
{ type: 'separator' },
{
label: '开发者选项',
submenu: [
{
label: '刷新',
accelerator: 'CmdOrCtrl+R',
role: 'reload'
},
{
label: '开发者工具',
accelerator: 'F12',
role: 'toggleDevTools'
}
]
}
])
contextMenu.popup(window)
}
// 在渲染进程中使用
webContents.on('context-menu', (event, params) => {
const contextMenu = Menu.buildFromTemplate([
{ label: '复制', role: 'copy', enabled: params.selectionText.length > 0 },
{ label: '粘贴', role: 'paste', enabled: params.editFlags.canPaste },
{ type: 'separator' },
{ label: `选中文字: "${params.selectionText}"` }
])
contextMenu.popup()
})
7.3 动态菜单(根据状态)
javascript
复制代码
function updateMenuState(isLoggedIn, userName) {
const template = [
{
label: '文件',
submenu: [
{ label: '新建', click: () => {} },
{ label: '打开', click: () => {} }
]
},
{
label: '账户',
submenu: isLoggedIn ? [
{ label: `用户: ${userName}` },
{ label: '退出登录', click: () => logout() }
] : [
{ label: '登录', click: () => showLogin() },
{ label: '注册', click: () => showRegister() }
]
}
]
const menu = Menu.buildFromTemplate(template)
Menu.setApplicationMenu(menu)
}
8. 平台差异
8.1 macOS vs Windows/Linux
| 特性 |
macOS |
Windows/Linux |
| 菜单位置 |
屏幕顶部(系统级) |
窗口顶部 |
| 角色默认行为 |
自动应用 |
需要手动设置 |
| sublabel |
支持 |
不支持 |
| toolTip |
支持 |
不支持 |
| 右键菜单样式 |
原生样式 |
Chromium 样式 |
8.2 Windows/Linux 快捷键前缀
javascript
复制代码
// Windows/Linux 可以用 & 设置快捷键
{
label: '&File', // Alt+F 打开文件菜单
submenu: [
{ label: '&New', accelerator: 'Ctrl+N' },
{ label: '&Open', accelerator: 'Ctrl+O' },
{ label: '&Save', accelerator: 'Ctrl+S' }
]
}
// 转义 & 字符
{ label: '&&Settings' } // 显示为 &Settings
8.3 禁用默认菜单
javascript
复制代码
// 禁用默认菜单
Menu.setApplicationMenu(null)
最佳实践
✅ 推荐做法
javascript
复制代码
// 1. 使用角色而不是手动实现
{ role: 'copy' } // ✅ 原生体验
// 2. 避免手动实现
{ label: '复制', click: () => document.execCommand('copy') } // ❌
// 3. 动态菜单使用模板方式
Menu.buildFromTemplate(template) // ✅
// 4. macOS 考虑系统菜单规范
❌ 避免做法
-
不要在 macOS 上手动设置 label/accelerator
javascript
复制代码
// macOS 会忽略这些值
{ role: 'copy', label: '复制' } // ❌
{ role: 'copy' } // ✅
-
不要忘记分隔线类型
javascript
复制代码
{ type: 'separator' } // ✅
{ label: '---' } // ❌
-
不要忽略 enabled 状态
javascript
复制代码
{ label: '删除', enabled: false } // 禁用时置灰显示
速查表
css
复制代码
Menu.setApplicationMenu(menu) 设置应用菜单
Menu.getApplicationMenu() 获取应用菜单
Menu.buildFromTemplate(template) 从模板构建菜单
css
复制代码
menu.popup(options) 弹出菜单
menu.closePopup() 关闭菜单
menu.append(item) 添加菜单项
menu.insert(pos, item) 插入菜单项
menu.getMenuItemById(id) 获取菜单项
css
复制代码
normal 普通菜单项
separator 分隔线
submenu 子菜单
checkbox 复选框
radio 单选按钮
常用角色
bash
复制代码
undo, redo, cut, copy, paste 编辑操作
reload, toggleDevTools 视图操作
minimize, close 窗口操作
togglefullscreen 全屏操作
文档基于 Electron v28+ Menu/MenuItem API 编写