Electron ShareMenu 详解:在 macOS 桌面应用中调用系统分享菜单(Share Menu)

发布时间:2026/9/7 8:26:07
Electron ShareMenu 详解:在 macOS 桌面应用中调用系统分享菜单(Share Menu) Electron ShareMenu 详解在 macOS 桌面应用中调用系统分享菜单Share Menu【免费下载链接】electron:electron: Build cross-platform desktop apps with JavaScript, HTML, and CSS项目地址: https://gitcode.com/GitHub_Trending/el/electronElectron 的ShareMenu类让 macOS 应用能够直接唤起系统级的分享菜单Share Menu把文本、文件或 URL 从当前上下文分享到 App、社交账号和其他服务。本文基于 Electron 仓库中的 API 文档 docs/api/share-menu.md、配套的 SharingItem 结构 以及主进程 JS/C 源码完整讲解其用法、参数默认值、底层实现链路以及如何把它以菜单子项shareMenurole的方式嵌入应用菜单。什么是 ShareMenuShareMenu是一个主进程Main process类用于在 macOS 上创建系统分享菜单。这个概念对应 Apple 的 Share ExtensionsHIG 中的 Share Menu机制用户点击分享后由系统枚举本机可用的分享目标信息、备忘录、AirDrop、各社交 App 等开发者不需要自己实现任何分享渠道。从 docs/api/share-menu.md 的 API history 注释看该 API 由上游 PR electron/electron#25629 引入。文档同时给出两条使用路径独立类new ShareMenu(sharingItem)然后popup()以右键上下文菜单的形式弹出——适合在页面某处点一下直接分享的交互菜单 role作为其他菜单的子菜单时改用MenuItem的shareMenurole见下文第五节。文档还沿用了 Electron 内置类的通用约束值得原样保留警告Electron 的内置类不能在用户代码中被继承subclassed详见 FAQ。分享内容的载体SharingItem 结构ShareMenu构造函数唯一参数是一个 SharingItem 对象它描述要分享什么。按 docs/api/structures/sharing-item.md 的定义它只有三个可选字段且都是数组字段类型说明textsstring[](optional)要分享的文本数组filePathsstring[](optional)要分享的文件路径数组urlsstring[](optional)要分享的 URL 数组三者可以任意组合例如一段文字 一个链接 两个图片文件const sharingItem { texts: [这是我在 My Electron App 中选中的内容], urls: [https://example.com/article/42], filePaths: [/tmp/screenshot-1.png, /tmp/screenshot-2.png] };这个结构不只是ShareMenu专用——它同样被MenuItem的sharingItem属性复用当role为shareMenu时生效两种入口共享同一份数据模型。创建与弹出new ShareMenu()与popup()new ShareMenu(sharingItem)const { ShareMenu } require(electron); const sharingItem { texts: [Hello from Electron] }; const shareMenu new ShareMenu(sharingItem);从源码看JS 层的ShareMenu是一个非常薄的包装见 lib/browser/api/share-menu.tsclass ShareMenu implements Electron.ShareMenu { private menu: Menu; constructor(sharingItem: SharingItem) { this.menu new (Menu as any)({ sharingItem }); } popup(options?: PopupOptions) { this.menu.popup(options); } closePopup(browserWindow?: BrowserWindow) { this.menu.closePopup(browserWindow); } }也就是说ShareMenu本质上是一个携带了sharingItem构造参数的Menu其弹出与关闭逻辑完全复用了 Menu 的既有实现。shareMenu.popup([options])把分享菜单作为上下文菜单弹出到BrowserWindow中。PopupOptions的参数及默认值如下完整继承自 docs/api/share-menu.md参数类型默认值说明browserWindowBrowserWindow (optional)当前聚焦窗口指定弹出所在的窗口xnumber (optional)当前鼠标光标位置若声明了y则必须同时声明ynumber (optional)当前鼠标光标位置若声明了x则必须同时声明positioningItemnumber (optional,macOS)-1指定哪个菜单项索引被定位到鼠标光标下方callbackFunction (optional)—菜单关闭时被调用这些默认值不是文档的口头承诺在 lib/browser/api/menu.ts 的Menu.prototype.popup实现中可以逐一验证x、y未传时默认置为-1由原生层解释为跟随鼠标光标第 114-115 行positioningItem未传时默认为-1第 116 行browserWindow的解析有一条回退链先校验传入窗口是否存在于BaseWindow.getAllWindows()中不存在则取getFocusedWindow()仍没有则取窗口列表第一个一个窗口都没有时直接抛出Cannot open Menu without a BaseWindow present第 120-129 行。典型用法例如在渲染进程右键后由主进程弹出// 在主进程中 const shareMenu new ShareMenu({ urls: [currentArticleUrl], texts: [currentTitle] }); // 在指定坐标弹出 shareMenu.popup({ browserWindow: mainWindow, x: 100, y: 200, callback: () console.log(分享菜单已关闭) }); // 或者跟随鼠标位置弹出不传 x/y shareMenu.popup();注意x/y的成对约束声明其中一个就必须同时声明另一个否则坐标语义不完整应按文档约定成对传入。shareMenu.closePopup([browserWindow])关闭在browserWindow默认聚焦窗口中弹出的该分享菜单shareMenu.closePopup(mainWindow); // 或 shareMenu.closePopup() 关闭聚焦窗口中的菜单底层实现见 lib/browser/api/menu.ts传入的窗口必须是BaseWindow实例此时按窗口 ID 精确关闭对应 runner若不传或不是BaseWindow则以-1作为参数表示关闭属于该菜单的所有runner。源码实现链路从 JS 选项到原生 NSMenu从源码结构看SharingItem的流转路径横跨 JS 与 C 两层且整条链路被 macOS 编译条件严格限定JS 层lib/browser/api/share-menu.ts 把sharingItem塞进Menu的构造参数对象中C 构造解析在 shell/browser/api/electron_api_menu.cc 中Menu::Menu的构造函数只在#if BUILDFLAG(IS_MAC)分支内读取options.Get(sharingItem, item)然后调用model_-SetSharingItem(std::move(item))写入ElectronMenuModel。这从编译层面确认了ShareMenu 仅支持 macOS——非 macOS 平台上传入的sharingItem会被静默忽略菜单模型回传 JSlib/browser/api/menu.ts 中Menu.prototype._getSharingItemForCommandId这一回调方法同样被process.platform darwin包裹即原生菜单在构建某个带分享能力的项时会通过 commandId 反查 JS 侧缓存的sharingItem原生 UI 构建最终消费发生在 shell/browser/ui/cocoa/electron_menu_controller.mmCocoa 平台实现。其中ConvertSharingItemToNS负责把SharingItem转换为NSObjects数组对应系统分享框架所需的NSItemProvider数据源createShareMenuForItem:再用该数组创建真正的原生分享菜单。这条链路解释了前文的两个行为特征为什么ShareMenu只是Menu的薄包装以及为什么平台差异被固化在编译分支而非运行时判断中。另一种用法作为菜单子项shareMenuroledocs/api/share-menu.md 明确指出想把分享菜单作为其他菜单的子菜单时不应使用ShareMenu类而应使用MenuItem的shareMenurole。在 docs/api/menu-item.md 中role的可选值包含shareMenu并配套一个专用属性sharingItemSharingItem (optional)macOS—— 当role为shareMenu时要分享的内容见 docs/api/menu-item.md 第 48、183 行的字段定义docs/tutorial/menus.md 的 role 列表中同样说明shareMenu对应的子菜单就是 share menu且必须同时设置sharingItem属性指明分享对象。示例——把分享项挂到文件菜单下const { Menu } require(electron); const template [ { label: 文件, submenu: [ { label: 分享, role: shareMenu, sharingItem: { texts: [来自 Electron 的分享内容], urls: [https://example.com] } }, { type: separator }, { role: quit } ] } ]; Menu.setApplicationMenu(Menu.buildFromTemplate(template));两种用法的选型原则需要跟随鼠标弹出、交互即开即关的场景用ShareMenu类 popup()需要常驻在应用菜单/右键菜单结构中时用shareMenurole 声明为子菜单。使用注意事项平台限制ShareMenu与sharingItem均为macOS专属能力。C 侧的解析代码位于BUILDFLAG(IS_MAC)编译分支shell/browser/api/electron_api_menu.cc在 Windows/Linux 上该 API 不会产生系统分享菜单跨平台应用应自行做process.platform darwin判断并提供降级交互不可继承与所有 Electron 内置类一样ShareMenu不能被用户代码extends见 docs/faq.md 的类继承说明坐标成对约束popup()的x与y必须同时声明或同时省略省略时回落到鼠标光标位置lib/browser/api/menu.ts 中默认值-1即此语义回调时机popup()的callback在菜单关闭时触发而非弹出时适合用于清理状态或恢复焦点closePopup()的作用域不传窗口参数时会关闭该菜单实例对应的所有 runnerlib/browser/api/menu.ts多窗口同时弹出同一ShareMenu时需注意这一点positioningItem用于多行菜单定位指定菜单打开后哪一行索引停在鼠标下方默认-1表示不做特殊定位。参考文件API 文档docs/api/share-menu.md、docs/api/structures/sharing-item.md、docs/api/menu-item.md、docs/tutorial/menus.mdJS 实现lib/browser/api/share-menu.ts、lib/browser/api/menu.ts原生实现shell/browser/api/electron_api_menu.cc、shell/browser/ui/cocoa/electron_menu_controller.mm【免费下载链接】electron:electron: Build cross-platform desktop apps with JavaScript, HTML, and CSS项目地址: https://gitcode.com/GitHub_Trending/el/electron创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考