跳到主要内容

Menu

类:Menu

创建原生应用菜单和上下文菜单。

进程:主进程

警告

Electron 的内置类不能在用户代码中被子类化。 更多信息请参阅常见问题

new Menu()

创建一个新菜单。

静态方法

Menu 类具有以下静态方法

  • menu Menu | null

在 macOS 上将 menu 设置为应用程序菜单。在 Windows 和 Linux 上,menu 将被设置为每个窗口的顶部菜单。

在 Windows 和 Linux 上,您还可以在顶级项名称中使用 & 来指示哪个字母应该获得生成的快捷键。例如,将文件菜单设置为 &File 会生成一个 Alt-F 快捷键,用于打开相关菜单。按钮标签中指示的字符会带下划线,并且 & 字符不会显示在按钮标签上。

为了在项名称中转义 & 字符,请在其前面添加一个 &。例如,&&File 将在按钮标签上显示 &File

传入 null 将禁用默认菜单。在 Windows 和 Linux 上,这还会导致窗口的菜单栏被移除。

注意

如果应用程序未设置菜单,将自动创建默认菜单。它包含 File (文件)、Edit (编辑)、View (视图)、Window (窗口) 和 Help (帮助) 等标准项。

返回 Menu | null - 如果已设置,则返回应用程序菜单;如果未设置,则返回 null

注意

返回的 Menu 实例不支持菜单项的动态添加或移除。实例属性 仍然可以动态修改。

  • action string

action 发送到应用程序的第一个响应者。这用于模拟 macOS 的默认菜单行为。通常,您会使用 role 属性的 MenuItem

有关 macOS 原生操作的更多信息,请参阅 macOS Cocoa 事件处理指南

  • template (MenuItemConstructorOptions | MenuItem)[]

返回 Menu

通常,template 是用于构建 MenuItemoptions 数组。用法可参考上方。

您还可以将其他字段附加到 template 的元素上,它们将成为构造的菜单项的属性。

实例方法

menu 对象具有以下实例方法

  • options Object (可选)
    • window BaseWindow (可选) - 默认为当前聚焦的窗口。
    • frame WebFrameMain (可选) - 如果您希望某些操作系统级别功能(例如 macOS 上的写作工具)正常工作,请提供相关框架。通常,这应该是 WebContents 上 context-menu 事件params.frame,或者是 WebContents 的 focusedFrame 属性
    • x number (可选) - 默认为当前鼠标光标位置。如果声明了 y,则必须声明 x
    • y number (可选) - 默认为当前鼠标光标位置。如果声明了 x,则必须声明 y
    • positioningItem number (可选) macOS - 菜单项的索引,用于在指定坐标处定位在鼠标光标下方。默认为 -1。
    • sourceType string (可选) Windows Linux - 这应该映射到 context-menu 事件提供的 menuSourceType。不建议手动设置此值,只提供您从其他 API 接收到的值或将其保留为 undefined。可以是 none (无)、mouse (鼠标)、keyboard (键盘)、touch (触摸)、touchMenu (触摸菜单)、longPress (长按)、longTap (长点击)、touchHandle (触摸手柄)、stylus (触控笔)、adjustSelection (调整选择) 或 adjustSelectionReset (重置选择调整)。
    • callback Function (可选) - 菜单关闭时调用。

BaseWindow 中将此菜单作为上下文菜单弹出。

  • window BaseWindow (可选) - 默认为当前聚焦的窗口。

关闭 window 中的上下文菜单。

menuItem 附加到菜单。

  • id string

返回 MenuItem | null 具有指定 id 的项

menuItem 插入到菜单的 pos 位置。

实例事件

使用 new Menu 创建或由 Menu.buildFromTemplate 返回的对象会触发以下事件

注意

某些事件仅在特定的操作系统上可用,并已进行标注。

事件:'menu-will-show'

返回

  • event Event

当调用 menu.popup() 时触发。

事件:'menu-will-close'

返回

  • event Event

当弹出菜单手动关闭或通过 menu.closePopup() 关闭时触发。

实例属性

menu 对象也具有以下属性

一个 MenuItem[] 数组,包含菜单的项。

每个 Menu 由多个 MenuItem 组成,并且每个 MenuItem 可以拥有一个子菜单。

示例

使用简单模板 API 创建应用程序菜单的示例

const { app, Menu } = require('electron')

const isMac = process.platform === 'darwin'

const template = [
// { role: 'appMenu' }
...(isMac
? [{
label: app.name,
submenu: [
{ role: 'about' },
{ type: 'separator' },
{ role: 'services' },
{ type: 'separator' },
{ role: 'hide' },
{ role: 'hideOthers' },
{ role: 'unhide' },
{ type: 'separator' },
{ role: 'quit' }
]
}]
: []),
// { role: 'fileMenu' }
{
label: 'File',
submenu: [
isMac ? { role: 'close' } : { role: 'quit' }
]
},
// { role: 'editMenu' }
{
label: 'Edit',
submenu: [
{ role: 'undo' },
{ role: 'redo' },
{ type: 'separator' },
{ role: 'cut' },
{ role: 'copy' },
{ role: 'paste' },
...(isMac
? [
{ role: 'pasteAndMatchStyle' },
{ role: 'delete' },
{ role: 'selectAll' },
{ type: 'separator' },
{
label: 'Speech',
submenu: [
{ role: 'startSpeaking' },
{ role: 'stopSpeaking' }
]
}
]
: [
{ role: 'delete' },
{ type: 'separator' },
{ role: 'selectAll' }
])
]
},
// { role: 'viewMenu' }
{
label: 'View',
submenu: [
{ role: 'reload' },
{ role: 'forceReload' },
{ role: 'toggleDevTools' },
{ type: 'separator' },
{ role: 'resetZoom' },
{ role: 'zoomIn' },
{ role: 'zoomOut' },
{ type: 'separator' },
{ role: 'togglefullscreen' }
]
},
// { role: 'windowMenu' }
{
label: 'Window',
submenu: [
{ role: 'minimize' },
{ role: 'zoom' },
...(isMac
? [
{ type: 'separator' },
{ role: 'front' },
{ type: 'separator' },
{ role: 'window' }
]
: [
{ role: 'close' }
])
]
},
{
role: 'help',
submenu: [
{
label: 'Learn More',
click: async () => {
const { shell } = require('electron')
await shell.openExternal('https://electron.js.cn')
}
}
]
}
]

const menu = Menu.buildFromTemplate(template)
Menu.setApplicationMenu(menu)

渲染进程

要创建由渲染进程发起的菜单,请使用 IPC 将所需信息发送到主进程,并由主进程代表渲染进程显示菜单。

以下是用户右键点击页面时显示菜单的示例

// renderer
window.addEventListener('contextmenu', (e) => {
e.preventDefault()
ipcRenderer.send('show-context-menu')
})

ipcRenderer.on('context-menu-command', (e, command) => {
// ...
})

// main
ipcMain.on('show-context-menu', (event) => {
const template = [
{
label: 'Menu Item 1',
click: () => { event.sender.send('context-menu-command', 'menu-item-1') }
},
{ type: 'separator' },
{ label: 'Menu Item 2', type: 'checkbox', checked: true }
]
const menu = Menu.buildFromTemplate(template)
menu.popup({ window: BrowserWindow.fromWebContents(event.sender) })
})

macOS 应用菜单注意事项

macOS 的应用菜单样式与 Windows 和 Linux 完全不同。以下是一些关于如何使您的应用菜单更符合原生风格的注意事项。

标准菜单

在 macOS 上有许多系统定义的标准菜单,例如 ServicesWindows 菜单。要使您的菜单成为标准菜单,您应该将菜单的 role 设置为以下之一,Electron 将识别它们并使其成为标准菜单

  • window
  • help
  • services

标准菜单项操作

macOS 为某些菜单项提供了标准操作,例如 About xxx (关于 xxx)、Hide xxx (隐藏 xxx) 和 Hide Others (隐藏其他)。要将菜单项的操作设置为标准操作,您应该设置菜单项的 role 属性。

在 macOS 上,应用程序菜单第一个项的标签始终是您应用的名称,无论您设置了什么标签。要更改它,请修改您应用包的 Info.plist 文件。有关更多信息,请参阅关于信息属性列表文件

可以使用 sublabel 选项向菜单项添加菜单子标签,或副标题。下面是基于上述渲染器示例的示例

// main
ipcMain.on('show-context-menu', (event) => {
const template = [
{
label: 'Menu Item 1',
sublabel: 'Subtitle 1',
click: () => { event.sender.send('context-menu-command', 'menu-item-1') }
},
{ type: 'separator' },
{ label: 'Menu Item 2', sublabel: 'Subtitle 2', type: 'checkbox', checked: true }
]
const menu = Menu.buildFromTemplate(template)
menu.popup({ window: BrowserWindow.fromWebContents(event.sender) })
})

为特定浏览器窗口设置菜单 (Linux Windows)

浏览器窗口的 setMenu 方法 可以设置特定浏览器窗口的菜单。

您可以使用 before (之前)、after (之后)、beforeGroupContaining (包含组之前)、afterGroupContaining (包含组之后) 和 id 来控制使用 Menu.buildFromTemplate 构建菜单时项的放置位置。

  • before (之前) - 将此项插入到具有指定 ID 的项之前。如果引用的项不存在,则该项将插入到菜单的末尾。这也意味着该菜单项应与引用的项位于同一“组”中。
  • after (之后) - 将此项插入到具有指定 ID 的项之后。如果引用的项不存在,则该项将插入到菜单的末尾。这也意味着该菜单项应与引用的项位于同一“组”中。
  • beforeGroupContaining (包含组之前) - 为单个上下文菜单提供了一种方式,使其可以声明其包含组放置在具有指定 ID 的项的包含组之前。
  • afterGroupContaining (包含组之后) - 为单个上下文菜单提供了一种方式,使其可以声明其包含组放置在具有指定 ID 的项的包含组之后。

默认情况下,除非使用指定的定位关键字之一,否则项将按照它们在模板中出现的顺序插入。

示例

模板

[
{ id: '1', label: 'one' },
{ id: '2', label: 'two' },
{ id: '3', label: 'three' },
{ id: '4', label: 'four' }
]

Menu

- 1
- 2
- 3
- 4

模板

[
{ id: '1', label: 'one' },
{ type: 'separator' },
{ id: '3', label: 'three', beforeGroupContaining: ['1'] },
{ id: '4', label: 'four', afterGroupContaining: ['2'] },
{ type: 'separator' },
{ id: '2', label: 'two' }
]

Menu

- 3
- 4
- ---
- 1
- ---
- 2

模板

[
{ id: '1', label: 'one', after: ['3'] },
{ id: '2', label: 'two', before: ['1'] },
{ id: '3', label: 'three' }
]

Menu

- ---
- 3
- 2
- 1