本文介绍:菜单

创建应用程序菜单和上下文菜单

进程: 主进程

new Menu()

用途:创建新菜单

静态方法

Menu.setApplicationMenu(menu)

用途:设置应用菜单(在macOS中为应用菜单,Windows 和 Linux中为窗口顶部菜单)

  • menu Menu

    注意: 这个API必须置于 app 模块的 ready之后.

Menu.getApplicationMenu()

用途:获取应用菜单

如果应用没有菜单的话,返回 null.有则返回菜单 Menu ,请注意,该返回菜单 Menu实例不支持动态添加或删除菜单项.但 实例属性 还是仍然支持动态修改.

Menu.sendActionToFirstResponder(action) macOS

用途:模拟 Cocoa 菜单的默认行为,发送 action 给应用的第一个响应器

  • action String

通常你只需使用 MenuItem 的属性role模拟macOS默认的菜单行为.

更多macOS原生action,请参阅macOS Cocoa事件处理指南

Menu.buildFromTemplate(template)

用途:template中创建菜单

  • template MenuItemConstructorOptions[]

返回 Menu,一般来说, template 只是用来构造 MenuItem 的数组 options .你也可以向 template 元素添加其它东西,使它们该菜单项的属性.

实例方法

menu.popup([browserWindow, options])

用途:在指定位置( x, y)弹出菜单

  • browserWindow BrowserWindow (可选) - 默认为聚焦窗口.
  • options Object(可选)
    • x Number (可选) - 当前光标的 x ,默认为 -1.
    • y Number (如果存在 x,则该项必须) -当前光标的 y.
    • async Boolean (可选) - 同异步设置, true为同步即立即返回调用, false则是选菜单被择或关闭等操作后返回, 默认为 false.
    • positioningItem Number (可选) macOS - 在指定坐标鼠标位置下面的菜单项的索引. 默认为 -1.弹出此菜单作为browserWindow中的上下文菜单.

menu.closePopup([browserWindow])

用途:关闭 browserWindow中打开的上下文菜单

  • browserWindow BrowserWindow (可选) - 默认为聚焦窗口.

menu.append(menuItem)

用途:menuItem附加到菜单

  • menuItem MenuItem

menu.insert(pos, menuItem)

用途:menuItem插入到菜单的 pos位置

  • pos Integer
  • menuItem MenuItem

实例属性

menu.items

一个包含菜单项的 MenuItem[]数组。每个Menu由多个MenuItem组成,每个 MenuItem可以有一个子菜单。

例子

Menu类仅在主进程中可用,但您也可以通过remote模块在渲染过程中使用它。

主进程

在主进程中创建应用程序菜单的示例:

  1. const {app, Menu} = require('electron')
  2. const template = [
  3. {
  4. label: 'Edit',
  5. submenu: [
  6. {
  7. role: 'undo'
  8. },
  9. {
  10. role: 'redo'
  11. },
  12. {
  13. type: 'separator'
  14. },
  15. {
  16. role: 'cut'
  17. },
  18. {
  19. role: 'copy'
  20. },
  21. {
  22. role: 'paste'
  23. },
  24. {
  25. role: 'pasteandmatchstyle'
  26. },
  27. {
  28. role: 'delete'
  29. },
  30. {
  31. role: 'selectall'
  32. }
  33. ]
  34. },
  35. {
  36. label: 'View',
  37. submenu: [
  38. {
  39. role: 'reload'
  40. },
  41. {
  42. role: 'forcereload'
  43. },
  44. {
  45. role: 'toggledevtools'
  46. },
  47. {
  48. type: 'separator'
  49. },
  50. {
  51. role: 'resetzoom'
  52. },
  53. {
  54. role: 'zoomin'
  55. },
  56. {
  57. role: 'zoomout'
  58. },
  59. {
  60. type: 'separator'
  61. },
  62. {
  63. role: 'togglefullscreen'
  64. }
  65. ]
  66. },
  67. {
  68. role: 'window',
  69. submenu: [
  70. {
  71. role: 'minimize'
  72. },
  73. {
  74. role: 'close'
  75. }
  76. ]
  77. },
  78. {
  79. role: 'help',
  80. submenu: [
  81. {
  82. label: 'Learn More',
  83. click () { require('electron').shell.openExternal('http://electron.atom.io') }
  84. }
  85. ]
  86. }
  87. ]
  88. if (process.platform === 'darwin') {
  89. template.unshift({
  90. label: app.getName(),
  91. submenu: [
  92. {
  93. role: 'about'
  94. },
  95. {
  96. type: 'separator'
  97. },
  98. {
  99. role: 'services',
  100. submenu: []
  101. },
  102. {
  103. type: 'separator'
  104. },
  105. {
  106. role: 'hide'
  107. },
  108. {
  109. role: 'hideothers'
  110. },
  111. {
  112. role: 'unhide'
  113. },
  114. {
  115. type: 'separator'
  116. },
  117. {
  118. role: 'quit'
  119. }
  120. ]
  121. })
  122. // 编辑菜单
  123. template[1].submenu.push(
  124. {
  125. type: 'separator'
  126. },
  127. {
  128. label: 'Speech',
  129. submenu: [
  130. {
  131. role: 'startspeaking'
  132. },
  133. {
  134. role: 'stopspeaking'
  135. }
  136. ]
  137. }
  138. )
  139. //窗口菜单
  140. template[3].submenu = [
  141. {
  142. label: 'Close',
  143. accelerator: 'CmdOrCtrl+W',
  144. role: 'close'
  145. },
  146. {
  147. label: 'Minimize',
  148. accelerator: 'CmdOrCtrl+M',
  149. role: 'minimize'
  150. },
  151. {
  152. label: 'Zoom',
  153. role: 'zoom'
  154. },
  155. {
  156. type: 'separator'
  157. },
  158. {
  159. label: 'Bring All to Front',
  160. role: 'front'
  161. }
  162. ]
  163. }
  164. const menu = Menu.buildFromTemplate(template)
  165. Menu.setApplicationMenu(menu)

渲染进程

使用remote模块在渲染进程中动态创建菜单的示例,当用户右击页面时显示:

  1. <!-- index.html -->
  2. <script>
  3. const {remote} = require('electron')
  4. const {Menu, MenuItem} = remote
  5. const menu = new Menu()
  6. menu.append(new MenuItem({label: 'MenuItem1', click() { console.log('item 1 clicked') }}))
  7. menu.append(new MenuItem({type: 'separator'}))
  8. menu.append(new MenuItem({label: 'MenuItem2', type: 'checkbox', checked: true}))
  9. window.addEventListener('contextmenu', (e) => {
  10. e.preventDefault()
  11. menu.popup(remote.getCurrentWindow())
  12. }, false)
  13. </script>

macOS应用程序菜单注意事项

相对于windows 和 linux, macOS 上的应用菜单是完全不同的样式,这里是一些注意事项,来让你的菜单项更原生化.

标准菜单

在macOS上有很多系统定义的标准菜单,例如 ServicesWindows菜单。要使菜单成为标准菜单,您设置菜单的 role 属性,Electron 将会自动识别,可选值有:

  • window
  • help
  • services

标准菜单项操作

macOS为某些菜单项提供了标准操作,例如 关于xxx隐藏xxx隐藏其他。要将菜单项操作设置为标准操作,你需要设置菜单的 role 属性。

主菜单的名称

在 macOS ,无论你设置的什么标签,应用菜单的第一个菜单项的标签始终未你的应用名字.

想要改变它的话,你必须通过修改应用程序包的 Info.plist 文件来修改应用名字.详见关于信息属性列表文件

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

浏览器窗口的setMenu 方法 可以设置某些浏览

菜单项位置

当通过 Menu.buildFromTemplate 创建菜单的时候,你可以使用 position and id 来放置菜单项. MenuItem 的属性 position 格式为 [placement]=[id], placement 取值为 before, after, 或 endof 三个参数, id 是已存在菜单项的唯一 ID:

  • before - 在指定id菜单项之前插入. 如果指定菜单项不存在,则将其插在菜单末尾.
  • after - 在指定id菜单项之后插入. 如果指定菜单项不存在,则将其插在菜单末尾.
  • endof - 在包含指定id菜单项的分组末尾插入. 如果指定菜单项不存在, 则将用id创建新的分组,并在分组中插入菜单项.

当某个菜单项插入成功后,未插入的其它菜单项会跟随插入.所以,如需在同位置插入一组菜单项,只需将这个组第一个菜单项插入指定位置.

示例

模板1:

  1. [
  2. {label: '4', id: '4'},
  3. {label: '5', id: '5'},
  4. {label: '1', id: '1', position: 'before=4'},
  5. {label: '2', id: '2'},
  6. {label: '3', id: '3'}
  7. ]

菜单1:

  1. - 1
  2. - 2
  3. - 3
  4. - 4
  5. - 5

模板2:

  1. [
  2. {label: 'a', position: 'endof=letters'},
  3. {label: '1', position: 'endof=numbers'},
  4. {label: 'b', position: 'endof=letters'},
  5. {label: '2', position: 'endof=numbers'},
  6. {label: 'c', position: 'endof=letters'},
  7. {label: '3', position: 'endof=numbers'}
  8. ]

菜单2:

  1. - ---
  2. - a
  3. - b
  4. - c
  5. - ---
  6. - 1
  7. - 2
  8. - 3