Electron 的菜单系统由三大核心模块构成:
特性 | Windows | macOS | Linux |
---|---|---|---|
菜单栏位置 | 窗口顶部 | 系统顶部栏 | 窗口顶部 |
快捷键显示 | 带下划线 | 右侧显示 | 带下划线 |
系统菜单项 | 无 | 有(关于/服务等) | 无 |
const { Menu } = require('electron')
const template = [
{
label: '文件',
submenu: [
{ label: '新建', accelerator: 'CmdOrCtrl+N' },
{ type: 'separator' },
{ label: '退出', role: 'quit' }
]
}
]
const menu = Menu.buildFromTemplate(template)
Menu.setApplicationMenu(menu)
Electron 预定义角色列表:
undo
/redo
- 撤销/重做cut
/copy
/paste
- 剪切板操作reload
- 刷新页面togglefullscreen
- 全屏切换{
label: '编辑',
submenu: [
{ role: 'undo' },
{ role: 'redo' },
{ type: 'separator' },
{ role: 'cut' },
{ role: 'copy' },
{ role: 'paste' }
]
}
// preload.js
const { contextBridge, ipcRenderer } = require('electron')
contextBridge.exposeInMainWorld('electron', {
showContextMenu: () => ipcRenderer.send('show-context-menu')
})
// renderer.js
window.addEventListener('contextmenu', (e) => {
e.preventDefault()
window.electron.showContextMenu()
})
// main.js
ipcMain.on('show-context-menu', (event) => {
const menu = Menu.buildFromTemplate([
{ label: '复制', role: 'copy' },
{ type: 'separator' },
{
label: '自定义操作',
click: () => event.sender.send('custom-action')
}
])
const win = BrowserWindow.fromWebContents(event.sender)
menu.popup({ window: win })
})
function updateMenu(editEnabled) {
const template = [
{
label: '编辑',
submenu: [
{
label: '保存',
enabled: editEnabled,
click: () => handleSave()
}
]
}
]
const menu = Menu.buildFromTemplate(template)
Menu.setApplicationMenu(menu)
}
// 主进程
const menu = Menu.buildFromTemplate([...])
menu.items[0].submenu.items[2].enabled = false
// 渲染进程通信
ipcRenderer.on('update-menu-state', (_, state) => {
const menuItem = Menu.getApplicationMenu().getMenuItemById('save-item')
menuItem.enabled = state
})
function createWindowWithMenu() {
const win = new BrowserWindow()
const menuTemplate = [
{
label: '窗口操作',
submenu: [
{
label: '关闭窗口',
click: () => win.close()
}
]
}
]
const menu = Menu.buildFromTemplate(menuTemplate)
win.setMenu(menu)
}
class MenuManager {
constructor() {
this.sharedTemplate = []
this.windowMenus = new Map()
}
registerWindow(winId, template) {
const mergedTemplate = [...this.sharedTemplate, ...template]
const menu = Menu.buildFromTemplate(mergedTemplate)
this.windowMenus.set(winId, menu)
}
}
let cachedMenu = null
function getMenu() {
if (!cachedMenu) {
cachedMenu = Menu.buildFromTemplate(heavyTemplate)
}
return cachedMenu
}
// 窗口关闭时释放菜单
win.on('closed', () => {
win.setMenu(null)
win = null
})
// 禁用危险操作
{
label: '危险操作',
enabled: false,
visible: process.env.NODE_ENV === 'development'
}
{
label: '执行命令',
click: () => {
if (validateCommand(safeCommand)) {
execute(safeCommand)
}
}
}
if (process.platform === 'darwin') {
template.unshift({
label: app.name,
submenu: [
{ role: 'about' },
{ type: 'separator' },
{ role: 'services' },
{ type: 'separator' },
{ role: 'hide' },
{ role: 'hideOthers' },
{ role: 'unhide' },
{ type: 'separator' },
{ role: 'quit' }
]
})
}
{
label: '保存',
accelerator: 'Ctrl+S',
acceleratorWhenHidden: true // 强制显示快捷键
}
const menu = Menu.buildFromTemplate(template)
menu.items.forEach(item => {
item.icon = nativeImage.createFromPath('[email protected]')
})
const editorMenu = {
label: '编辑',
submenu: [
{ role: 'undo' },
{ role: 'redo' },
{ type: 'separator' },
{
label: '代码操作',
submenu: [
{ label: '格式化' },
{ label: '重构' },
{ label: '分析' }
]
}
]
}
function loadPluginMenus() {
plugins.forEach(plugin => {
const menuItem = {
label: plugin.name,
submenu: plugin.getMenuItems()
}
mainTemplate.push(menuItem)
})
}
function buildLocalizedMenu(lang) {
return {
label: i18n.t('menu.file', { lang }),
submenu: [
{ label: i18n.t('menu.newFile', { lang }) }
]
}
}
/* 菜单样式适配 */
.menu:dir(rtl) {
text-align: right;
padding-right: 20px;
}
// 开启调试模式
Menu.setApplicationMenu(Menu.buildFromTemplate([
{
label: '调试',
submenu: [
{ role: 'toggleDevTools' }
]
}
]))
describe('Menu Test', () => {
it('should have correct menu items', async () => {
const menu = await app.client.getMenu()
assert(menu.find(item => item.label === '文件'))
})
})
通过合理运用 Electron 的菜单系统,开发者可以实现:
建议开发者定期查阅 Electron 官方文档 获取最新 API 信息,同时结合用户反馈持续优化菜单设计。在保持功能强大的同时,始终将用户体验放在首位,方能打造真正优秀的桌面应用程序。