菜單
創建原生應用菜單和上下文菜單。
進程:主進程
new Menu()
創建新菜單。
靜態方法
Menu類有以下方法:
Menu.setApplicationMenu(menu)
menuMenu | null
在macOS上將 menu設置成應用內菜單
在windows和Linux上,menu 將會被設置成窗口頂部菜單
在Windows和Linux中,可以在菜單的頂層標簽的某個字母前添加&以綁定快捷鍵。 例如,使用&File后可以使用Alt-F呼出File的子選項。 被綁定快捷鍵的字母將會以下划線標出。 &並不會在運行時顯示
傳遞 null 值可以禁用默認菜單。 在 Windows 和 Linux 上,使用此方法移除窗口上的菜單欄可能會有額外的效果。
注釋:如果應用沒有設置菜單的話,系統會生成一個默認菜單。 默認生成的菜單中包含了一些初始選項,例如 文件,編輯, 視圖,窗口,幫助。
EN
Menu.getApplicationMenu()
返回 Menu | null - 如果有設置, 則返回應用程序菜單, 如果沒設置,則返回 null。
注釋:返回的 Menu實例不支持動態添加或刪除菜單項, 但仍然可以動態修改 實例屬性 。
EN
Menu.sendActionToFirstResponder(action) macOS
actionString
將 action 發送到應用程序的第一個響應方。 這用於模擬默認的 macOS 菜單行為。 通常你可以使用MenuItem的role屬性
有關 macOS 的本地操作的詳細信息, 請參閱 macOS Cocoa Event Handling Guide 。
EN
Menu.buildFromTemplate(template)
template(MenuItemConstructorOptions | MenuItem)[]
返回 Menu
一般來說, template是一個options類型的數組,用於構建MenuItem。 使用方法可參考前文。
You can also attach other fields to the element of the template and they will become properties of the constructed menu items.
實例方法
menu 對象具有以下實例方法:
menu.popup([options\])
-
optionsObject (可選)
windowBrowserWindow (可選) - 默認為選中窗口.xNumber (可選) - 默認為當前鼠標的位置。 如果指定了y,則該選項必選。yNumber (可選) - 默認為當前鼠標的位置。 如果指定了x,則該選項必選。positioningItemNumber (optional) macOS - The index of the menu item to be positioned under the mouse cursor at the specified coordinates. 默認值為 -1。callbackFunction (optional) - 會在菜單關閉后被調用.
將此菜單作為 browserWindow 中的上下文菜單彈出。
menu.closePopup([browserWindow])
-
browserWindowBrowserWindow (可選) - 默認為選中窗口.
關閉 browserWindow 中的上下文菜單。
menu.append(menuItem)
menuItem菜單項
將 menuItem 追加到菜單。
menu.getMenuItemById(id)
idString
Returns MenuItem | null the item with the specified id
menu.insert(pos, menuItem)
posIntegermenuItem菜單項
將 menuItem 插入菜單的 pos 位置。
實例事件
Objects created with new Menu or returned by Menu.buildFromTemplate emit the following events:
注意: 某些事件僅在特定的操作系統上可用, 這些方法會被標記出來。
事件: 'menu-will-show'
返回:
eventEvent
調用menu.popup()事件時觸發該事件。
事件: 'menu-will-close'
返回:
eventEvent
手動關閉彈出,或使用 menu.closePopup()方法關閉彈出時,觸發該事件。
實例屬性
menu 對象還具有以下屬性:
menu.items
包含菜單項的 MenuItem [] 數組。
每個 菜單 由多個 MenuItem 組成, 每個 MenuItem 可以有子菜單。
菜單項
添加菜單項到應用程序菜單和上下文菜單中
進程:主進程
有關示例, 請參見 Menu。
在
new MenuItem(可選)
-
選項對象
-
click功能(可選)-
click(menuItem, browserWindow, event)單擊菜單項時將調用。
menuItem菜單項browserWindowBrowserWindow | 未定義-如果未打開任何窗口,則不會定義。eventKeyboardEvent
-
role字符串(可選) -可以是undo,redo,cut,copy,paste,pasteAndMatchStyle,delete,selectAll,reload,forceReload,toggleDevTools,resetZoom,zoomIn,zoomOut,togglefullscreen,window,minimize,close,help,about,services,hide,hideOthers,unhide,quit,startSpeaking,stopSpeaking,zoom,front,appMenu,fileMenu,editMenu,viewMenu,recentDocuments,toggleTabBar,selectNextTab,selectPreviousTab,mergeAllWindows,clearRecentDocuments,moveTabToNewWindow或windowMenu-定義菜單項的動作,當指定該click屬性時將被忽略。見角色 -
typeString (可選)-可以是normal、separator、submenu、checkbox或radio。 -
labelString (可選) -
sublabelString (可選) -
toolTip字符串(可選)macOS-懸停此菜單項的文本。 -
acceleratorAccelerator (可選) -
icon(NativeImage | String) (可選) -
enabledBoolean (可選) - 如果為 false,該菜單項將會置灰且不可點擊。 -
acceleratorWorksWhenHidden布爾值(可選)macOS-默認為true,當false項目不可見時,將阻止加速器觸發該項目。 -
visibleBoolean (可選)-如果為 false, 該菜單項將完全隱藏。 -
checkedBoolean (可選)-只應為checkbox或radio類型菜單項指定。 -
registerAccelerator布爾值(可選)Linux Windows-如果為false,則不會在系統中注冊加速器,但仍會顯示該加速器。默認值true。 -
submenu(MenuItemConstructorOptions[] | Menu) (optional) - Should be specified forsubmenutype menu items. Ifsubmenuis specified, thetype: 'submenu'can be omitted. 如果該值不屬於Menu,它將被函數Menu.buildFromTemplate自動轉換。 -
id字符串(可選)-在單個菜單中唯一。如果已定義,則可以通過position屬性將其用作對此項目的引用。 -
beforeString [](可選)-將此項目插入具有指定標簽的項目之前。如果所引用的項目不存在,則該項目將插入菜單的末尾。還意味着所討論的菜單項應與該菜單項位於同一“組”中。 -
afterString[] (optional) - Inserts this item after the item with the specified label. 如果引用值不存在,那么該菜單項會插在這個菜單的尾部。 -
beforeGroupContainingString [](可選)-為單個上下文菜單提供一種方法,以聲明其包含組在具有指定標簽的項目的包含組之前的位置。 -
afterGroupContainingString [](可選)-為單個上下文菜單提供一種方法,以聲明其包含組在具有指定標簽的項目的包含組之后的位置。
-
注意: acceleratorWorksWhenHidden只在MacOS中生效,因為在Windows和Linux中快捷鍵不會隨着隱藏菜單項而失效。 該選項讓用戶可以選擇關閉,因為這是本地 macOS 開發中的可能。 此屬性只能在macOS High Sierra 10.13或以上中使用。
在
角色
可以通過角色來為menu添加預定義行為。
最好給任何一個菜單指定 role去匹配一個標准角色, 而不是嘗試在 click 函數中手動實現該行為。 內置的 role 行為將提供最佳的原生體驗。
使用 role 時, label 和 accelerator 值是可選的, 並為每個平台,將默認為適當值。
每個菜單項必須有一個role,label或在分離器的情況下type。
role 屬性可以具有以下值:
undoabout-觸發本機“關於”面板(Window上的自定義消息框,不提供其自身的框)。redocutcopypastepasteAndMatchStyleselectAlldeleteminimize- 最小化當前窗口。close- 關閉當前窗口.quit- 退出程序reload- 重新加載當前窗口。forcereload- 忽略緩存,重新加載當前窗口。toggledevtools- 在當前窗口中隱藏/顯示開發者工具。togglefullscreen- 將當前窗口切換至全屏模式。resetzoom- 將主頁的縮放級別重置為初始大小.zoomin- 主頁面放大 10%.zoomout-主頁面縮小 10%.fileMenu-整個默認的“文件”菜單(關閉/退出)editMenu-默認的 "編輯" 菜單 (包括撤消、復制等)viewMenu-整個默認的“查看”菜單(重新加載,切換開發者工具等)windowMenu-整個默認的“窗口”菜單(最小化,縮放等)。
以下附加角色在macOS上可用:
appMenu-整個默認的“應用”菜單(關於,服務等)hide-映射到hide操作.hideOthers-映射到hideOtherApplications操作.unhide-映射到unhideAllApplications操作.startSpeaking-映射到startSpeaking操作.stopSpeaking-映射到stopSpeaking操作.front-映射到arrangeInFront操作.zoom-映射到performZoom操作.toggleTabBar-映射到toggleTabBar操作.selectNextTab- 映射到selectNextTab操作.selectPreviousTab- 映射到selectPreviousTab操作.mergeAllWindows- 映射到mergeAllWindows操作.moveTabToNewWindow- 映射到moveTabToNewWindow操作.window- 這個子菜單是"Window" 菜單.help-這個子菜單是 "Help" 菜單.services-子菜單是“服務”菜單。這僅適用於在應用程序菜單使用,是不一樣的MacOS應用程序上下文菜單中使用的“服務”子菜單,這是不是在電子實現。recentDocuments-這個子菜單是 "Open Recent" 菜單.clearRecentDocuments-映射到clearRecentDocuments操作.
在 macOS 上指定 role 時, label 和 accelerator 是影響菜單項的唯一選項。 所有其它選項都將被忽略。 不過,仍然支持小寫的role,如toggledevtools。
諾塔Bene的:在enabled和visibility屬性不可用於在MacOS托盤頂級菜單項。
在
實例屬性
以下為 MenuItem 實例的可用屬性:
在
menuItem.id
String 指定了該選項唯一的id,此屬性可被動態更改。
在
menuItem.label
一個String指示項目的可見標簽。
在
menuItem.click
當 MenuItem 接收到 click 事件時激發的Function. It can be called with menuItem.click(event, focusedWindow, focusedWebContents).
eventKeyboardEventfocusedWindow瀏覽器窗口focusedWebContents網頁內容
在
menuItem.submenu
一個Menu(可選)包含菜單項的子菜單(如果有)。
在
menuItem.type
String 表示菜單項的類型 Can be normal, separator, submenu, checkbox or radio.
在
menuItem.role
String`(可選) 指出菜單項的角色 Can be `undo`, `redo`, `cut`, `copy`, `paste`, `pasteAndMatchStyle`, `delete`, `selectAll`, `reload`, `forceReload`, `toggleDevTools`, `resetZoom`, `zoomIn`, `zoomOut`, `togglefullscreen`, `window`, `minimize`, `close`, `help`, `about`, `services`, `hide`, `hideOthers`, `unhide`, `quit`, `startSpeaking`, `stopSpeaking`, `zoom`, `front`, `appMenu`, `fileMenu`, `editMenu`, `viewMenu`, `recentDocuments`, `toggleTabBar`, `selectNextTab`, `selectPreviousTab`, `mergeAllWindows`, `clearRecentDocuments`, `moveTabToNewWindow` or `windowMenu
在
menuItem.accelerator
一個Accelerator(可選)指示項目的加速器(如果已設置)。
在
menuItem.icon
A NativeImage | String(可選),指示項目的圖標(如果已設置)。
在
menuItem.sublabel
一個String指示項目的子標簽。
在
menuItem.toolTip 蘋果系統
一個String指示項目的懸停文本。
在
menuItem.enabled
一個 Boolean 類型的值, 指示是否啟用該項, 該屬性可以動態改變
在
menuItem.visible
一個 Boolean 類型的值, 指示該項是否可見, 該屬性可以動態改變。
在
menuItem.checked
一個 Boolean 類型的值, 指示是否選中該項, 該屬性可以動態改變。
checkbox 菜單項將在選中時切換 checked 的開關屬性。
單選菜單項 將返回單擊時checked屬性, 並將關閉同一菜單中所有相鄰項的屬性。
你可以為其他行為添加click函數。
在
menuItem.registerAccelerator
一個Boolean指示是否加速器應與系統進行注冊,或只是顯示。
此屬性可以動態更改。
在
menuItem.commandId
一個Number指示項目的順序唯一ID。
在
menuItem.menu
Menu該項目所屬的A。
示例
Menu 僅在主進程( main process)中可用, 但您也可以在渲染進程(render process)中通過 remote 模塊使用它。
主進程
在主進程中創建程序菜單的簡單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://electronjs.org')
}
}
]
}
]
const menu = Menu.buildFromTemplate(template)
Menu.setApplicationMenu(menu)
渲染進程
下面是通過 remote 模塊在網頁(render process)中動態創建右擊菜單的示例:
<!-- index.html -->
<script>
const { remote } = require('electron')
const { Menu, MenuItem } = remote
const menu = new Menu()
menu.append(new MenuItem({ label: 'MenuItem1', click() { console.log('item 1 clicked') } }))
menu.append(new MenuItem({ type: 'separator' }))
menu.append(new MenuItem({ label: 'MenuItem2', type: 'checkbox', checked: true }))
window.addEventListener('contextmenu', (e) => {
e.preventDefault()
menu.popup({ window: remote.getCurrentWindow() })
}, false)
</script>
MacOS中應用菜單注意事項
macOS 相比於 Windows 和 Linux 有着完全不同的應用程序菜單。 以下是一些有關使應用菜單更像原生應用菜單的注意事項。
標准菜單
MacOS有一些系統預定義的菜單,像是Services and Windows。 讓你的菜單更像MacOS標准菜單,只需設置菜單role值為如下示之一,Electron便會自動認出並設置成標准菜單,:
windowhelpservices
標准菜單項操作
macOS 已經為某些菜單項提供了標准操作, 如 about xxx 、Hide xxx和 Hide Others 。 若要將菜單項的操作設置為標准操作, 應設置菜單項的 role 屬性。
主菜單的名稱
在 macOS 中應用程序菜單的第一個項目的標簽總是你的應用程序的名字, 無論你設置什么標簽。 如要更改它, 請修改應用程序包的 Info. plist 文件。 有關詳細信息, 請參閱 About Information Property List Files 。
設置特定瀏覽器窗口的菜單 ( Linux Windows )
瀏覽器窗口的 setMenu 方法 可以設置特定瀏覽器窗口的菜單。
菜單項位置
你可以使用 before, after, beforeGroupContaining, afterGroupContaining 和 id 來控制由 Menu.buildFromTemplate 生成的菜單項的位置.
before- 在指定的標簽之前插入菜單項。 如果引用值不存在,那么該菜單項會插在這個菜單的尾部。 這還意味着,菜單項應該被放置在與引用項相同的組中。after- 在指定的標簽之后插入菜單項。 如果引用值不存在,那么該菜單項會插在這個菜單的尾部。 這還意味着,菜單項應該被放置在與引用項相同的組中。beforeGroupContaining- Provides a means for a single context menu to declare the placement of their containing group before the containing group of the item with the specified label.afterGroupContaining- Provides a means for a single context menu to declare the placement of their containing group after the containing group of the item with the specified label.
默認情況下,除非有位置相關的屬性,所有的菜單項會按照模板中的順序排放。
示例
模板:
[
{ id: '1', label: 'one' },
{ id: '2', label: 'two' },
{ id: '3', label: 'three' },
{ id: '4', label: 'four' }
]
菜單:
- 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' }
]
菜單:
- 3
- 4
- ---
- 1
- ---
- 2
模板:
[
{ id: '1', label: 'one', after: ['3'] },
{ id: '2', label: 'two', before: ['1'] },
{ id: '3', label: 'three' }
]
菜單:
- ---
- 3
- 2
- 1
案例
在主進程中渲染菜單
主進程
//為了管理應用程序的生命周期事件以及創建和控制瀏覽器窗口,您從 electron 包導入了 app 和 BrowserWindow 模塊 。
const { app, BrowserWindow,Menu } = require('electron')
//在此之后,你定義了一個創建 新的瀏覽窗口的函數並將 nodeIntegration 設置為 true,將 index.html 文件加載到窗口中(第 12 行,稍后我們將討論該文件)
function createWindow () {
const win = new BrowserWindow({
width: 800,
height: 600,
webPreferences: {
//是否注入nodeapi
nodeIntegration: true,
//渲染進程是否啟用remote模塊
enableRemoteModule: true
}
})
win.loadFile('index.html')
}
//你通過調用 createWindow方法,在 electron app 第一次被初始化時創建了一個新的窗口。
app.whenReady().then(createWindow)
//您添加了一個新的偵聽器,當應用程序不再有任何打開窗口時試圖退出。 由於操作系統的 窗口管理行為 ,此監聽器在 macOS 上是禁止操作的
app.on('window-all-closed', () => {
if (process.platform !== 'darwin') {
app.quit()
}
})
//您添加一個新的偵聽器,只有當應用程序激活后沒有可見窗口時,才能創建新的瀏覽器窗口。 例如,在首次啟動應用程序后或重啟運行中的應用程序
app.on('activate', () => {
if (BrowserWindow.getAllWindows().length === 0) {
createWindow()
}
})
//5s后
setTimeout(()=>{
//menu item
const template = [
{label: "第一個菜單項目"},
{label: "第二個菜單項目"},
{role: "undo"},
{type: 'separator'},
{label: "第三個菜單項目"},
{label: "第四個菜單項目"},
];
//使用 menu item 創建menu對象
const menu = Menu.buildFromTemplate(template);
//設置菜單
Menu.setApplicationMenu(menu);
//彈出菜單
menu.popup();
}, 5000)
渲染進程
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>菜單</title>
</head>
<body>
<h1>菜單</h1>
</body>
</html>
效果

渲染進程中使用菜單並注冊點擊事件使用MenuItem
渲染進程
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>菜單</title>
</head>
<body>
<h1>菜單</h1>
<button onclick="openMenu()">點擊彈出菜單</button>
</body>
<script>
const { Menu, MenuItem } = require('electron').remote
function openMenu() {
//menu item
const template = [
{label: "第一個菜單項目"},
{label: "第二個菜單項目"},
{role: "undo"},
{type: 'separator'},
{label: "第三個菜單項目"},
{label: "第四個菜單項目"},
{label: "點擊測試", click : () => {
console.log('點擊事件觸發.....');
}
},
];
//使用 menu item 創建menu對象
const menu = Menu.buildFromTemplate(template);
//設置成應用菜單
//Menu.setApplicationMenu(menu);
//使用MenuItem
let item = new MenuItem({label : '這是MenuItem'});
menu.append(item);
//彈出菜單
menu.popup();
}
</script>
</html>

渲染進程中創建帶子菜單的菜單
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>菜單</title>
</head>
<body>
<h1>菜單</h1>
<button onclick="openMenu()">點擊彈出菜單</button>
</body>
<script>
const { Menu, MenuItem } = require('electron').remote
function openMenu() {
//menu item
const template = [
{label: "第一個菜單項目"},
{label: "第二個菜單項目"},
{role: "undo"},
{type: 'separator'},
{label: "第三個菜單項目"},
{label: "第四個菜單項目"},
{label: "點擊測試", click : () => {
console.log('點擊事件觸發.....');
}
},
new MenuItem({label : '這是子菜單測試', submenu:[
{label: '子菜單1'},
{label: '子菜單2'},
{label: '子菜單3'}
]})
];
//使用 menu item 創建menu對象
const menu = Menu.buildFromTemplate(template);
//設置成應用菜單
//Menu.setApplicationMenu(menu);
//使用MenuItem
let item = new MenuItem({label : '這是MenuItem'});
menu.append(item);
//彈出菜單
menu.popup();
}
</script>
</html>

