Electron 原生功能集成

菜单、托盘、通知、剪贴板、对话框、快捷键与开机自启。

Intermediate
Key Points这些能力都在主进程:Menu 做菜单,Tray 做托盘,Notification 做通知,dialog 做文件对话框。

应用菜单

JavaScript
const { Menu, shell } = require('electron');

const template = [
  {
    label: '文件',
    submenu: [
      { label: '打开…', accelerator: 'CmdOrCtrl+O',
        click: () => openFile() },
      { label: '保存', accelerator: 'CmdOrCtrl+S',
        click: () => saveFile() },
      { type: 'separator' },
      { role: 'quit', label: '退出' }
    ]
  },
  {
    label: '编辑',
    submenu: [
      { role: 'undo', label: '撤销' },
      { role: 'redo', label: '重做' },
      { type: 'separator' },
      { role: 'cut', label: '剪切' },
      { role: 'copy', label: '复制' },
      { role: 'paste', label: '粘贴' }
    ]
  },
  {
    label: '帮助',
    submenu: [
      { label: '官网', click: () => shell.openExternal('https://example.com') }
    ]
  }
];

Menu.setApplicationMenu(Menu.buildFromTemplate(template));

role gives built-in behaviour Electron implements for you (copy, paste, quit, toggleDevTools), more reliable than hand-written callbacks. Custom items use label + click.

托盘

JavaScript
const { Tray, Menu, nativeImage, app } = require('electron');
const path = require('node:path');

let tray = null;

app.whenReady().then(() => {
  const icon = nativeImage.createFromPath(path.join(__dirname, 'icon.png'));
  tray = new Tray(icon.resize({ width: 16, height: 16 }));
  tray.setToolTip('我的应用');

  tray.setContextMenu(Menu.buildFromTemplate([
    { label: '显示主窗口', click: () => mainWindow.show() },
    { type: 'separator' },
    { label: '退出', click: () => app.quit() }
  ]));

  tray.on('click', () => {
    mainWindow.isVisible() ? mainWindow.hide() : mainWindow.show();
  });
});

Keep the tray icon in a global variable. A local one gets garbage-collected and the icon vanishes after a while — a classic Electron trap.

系统通知

JavaScript
const { Notification } = require('electron');

function notify(title, body) {
  if (!Notification.isSupported()) return;
  new Notification({
    title,
    body,
    icon: path.join(__dirname, 'icon.png'),
    silent: false
  }).show();
}

On Windows, notifications need an AppUserModelID or they may appear as electron.app.Electron. Packaging usually fixes it; during development call app.setAppUserModelId('com.example.app').

对话框

JavaScript
const { dialog } = require('electron');

// 打开文件
const { canceled, filePaths } = await dialog.showOpenDialog(mainWindow, {
  title: '选择文件',
  properties: ['openFile', 'multiSelections'],
  filters: [{ name: '文本', extensions: ['txt', 'md'] }]
});
if (!canceled) console.log(filePaths);

// 保存文件
const save = await dialog.showSaveDialog(mainWindow, {
  defaultPath: 'notes.md',
  filters: [{ name: 'Markdown', extensions: ['md'] }]
});

// 确认框
const { response } = await dialog.showMessageBox(mainWindow, {
  type: 'question',
  buttons: ['取消', '确定'],
  defaultId: 1,
  cancelId: 0,
  message: '确定删除这条记录?',
  detail: '删除后无法恢复。'
});
if (response === 1) doDelete();

Passing the window as the first argument makes the dialog modal to that window; omitting it attaches the dialog to the app, where it can hide behind another window and be lost.

剪贴板与全局快捷键

JavaScript
const { clipboard, globalShortcut } = require('electron');

clipboard.writeText('复制到剪贴板的内容');
const text = clipboard.readText();
const img = clipboard.readImage();

app.whenReady().then(() => {
  globalShortcut.register('CommandOrControl+Shift+K', () => {
    mainWindow.show();
    mainWindow.focus();
  });
});

app.on('will-quit', () => globalShortcut.unregisterAll());
A global shortcut steals the key combination system-wide, and a failed registration returns false instead of throwing. Check the return value and call unregisterAll() on quit, or hot reloads pile up conflicting registrations.

开机自启

JavaScript
app.setLoginItemSettings({
  openAtLogin: true,
  openAsHidden: true,        // macOS:启动后不显示窗口
  args: ['--hidden']
});

const { openAtLogin } = app.getLoginItemSettings();

Linux does not support this API; it needs a .desktop file in ~/.config/autostart/. Branch on process.platform for cross-platform support.

Friends & Partners