Electron 原生体验:菜单、托盘、快捷键与通知集成

Electron 的价值不只在于「把 Web 页面塞进桌面壳里」,还在于可以利用桌面系统的各种原生入口:菜单栏、托盘、全局快捷键、系统通知、文件关联等。
这一篇不追求 API 覆盖,而是从体验和架构的角度,讲清楚几件事:哪些地方适合用原生能力增强体验、这些能力应该放在主进程的哪一层,以及在设计时要注意哪些边界。

桌面应用中的菜单,通常承担几个职责:

  • 提供一份「全局功能地图」:文件/编辑/视图/帮助等;
  • 暴露某些不常用但重要的功能(导入导出、偏好设置、检查更新);
  • 显示当前上下文相关的操作(右键菜单)。

在 Electron 中,菜单由主进程管理:

  • 应用菜单(顶栏菜单)通过 MenuMenu.buildFromTemplate 创建;
  • 右键菜单可以在主/渲染进程中组合创建,但最终由主进程控制。

一个健康的模式是:

  • 菜单项的点击事件在主进程中转化为「命令」或「消息」;
  • 渲染进程监听这些命令/消息,执行具体 UI 逻辑。

例如:

  • 菜单里有「切换主题」项 → 主进程发送 IPC 消息 → 渲染进程更新主题状态;
  • 菜单里有「打开开发者工具」项 → 主进程直接对某个窗口的 webContents.openDevTools()

这样可以保持:

  • 菜单配置收敛在主进程;
  • 业务 UI 逻辑仍然集中在渲染进程,避免跨进程散落。

托盘图标(系统通知区域的小图标)常用于:

  • 持续运行的常驻应用(IM、同步工具、下载器);
  • 提供快速入口(打开主界面、展示状态、退出、切换模式)。

在 Electron 里,托盘由主进程通过 new Tray(iconPath) 创建,并可绑定菜单:

  • 通过 tray.setContextMenu(menu) 设置右键菜单;
  • 通过 tray.setToolTip 设置悬停提示。

典型模式是:

  • 当用户点击关闭按钮时:
    • 不直接退出应用,而是隐藏主窗口,托盘图标仍然存在;
    • 右键托盘菜单里提供「完全退出」选项。
  • 当用户点击托盘图标(或菜单项)时:
    • 如果窗口不存在,创建一个;
    • 如果窗口已存在但隐藏,重新显示并聚焦。

这样可以:

  • 让应用「看起来」退出但实际上在后台工作;
  • 减少启动等待时间,尤其适合需要常驻的应用。

Electron 支持在主进程注册全局快捷键(globalShortcut.register),应用可以在未聚焦时响应按键。
适合用在:

  • 需要随时呼出的输入框或面板(如命令面板、全局搜索);
  • 截图、录屏等需要跨应用触发的功能。
  • 避免抢占常见快捷键(如系统级组合或其他应用常用组合);
  • 提供设置页面,让用户可以自定义或关闭全局快捷键;
  • 在应用退出或窗口全部关闭时,确保注销(globalShortcut.unregisterAll()),避免残留。

在架构上,可以把全局快捷键处理逻辑整理成一个独立模块:

  • 与主进程的窗口管理、IPC 管理配合;
  • 避免在多个文件里分散注册/注销逻辑。

桌面通知适合用来:

  • 传达「异步完成」的结果(下载完成、任务结束、构建成功/失败);
  • 提醒用户需要关注的状态变化(新消息、提醒事项)。

不适合用来:

  • 高频刷屏、营销推送;
  • 代替 UI 内的明确反馈(按钮点击后是否生效等)。

在 Electron 中,通知可以由主进程或渲染进程触发(取决于版本和 API 使用方式)。
更稳妥的做法是:

  • 在业务层用统一的「通知服务」接口发起通知请求;
  • 由主进程判断当前平台/系统权限,决定是用 Notification API、系统托盘闪烁,还是直接在 UI 内给出提示。

这样可以避免:

  • 在很多地方直接 new Notification,难以统一管理频率与样式;
  • 在不同平台行为不一致,导致体验割裂。

除了菜单、托盘、快捷键和通知外,Electron 还可以:

  • 注册文件关联:双击某类文件自动用应用打开;
  • 注册自定义协议:点击形如 myapp:// 的链接自动唤起应用。

这类能力适合用在:

  • 文档/项目管理类应用,需要成为某些文件类型的默认编辑/查看器;
  • 与 Web/其他应用联动的场景,通过协议快速跳转到应用内的特定页面或资源。

工程上需要注意:

  • 关联前给用户明确选择与说明;
  • 提供取消关联或修改默认行为的入口;
  • 对接收到的外部输入(文件路径、URL 参数)做完整验证。

可以用几条原则来概括这一篇:

  • 把菜单、托盘、快捷键、通知、文件/协议关联当成「系统入口」,而不是单纯的 API 玩具;
  • 原生能力的定义和注册集中放在主进程,由清晰的模块管理,并通过 IPC 或本地 API 与渲染进程对接具体业务;
  • 在设计体验时,尊重操作系统和用户的习惯,避免过度打扰或抢占全局资源。

在这些原则之上,Electron 应用既能保持 Web 技术带来的开发效率,又能在桌面环境中给出足够自然的原生体验。