{T}

Electron App 模块

介绍

app 模块是 Electron 应用程序的核心,它负责管理整个应用程序的生命周期。该模块只能在 主进程 中使用

核心功能

  • 生命周期管理: 控制应用的启动、退出、以及在不同阶段触发的事件
  • 系统集成: 与操作系统进行交互,例如修改 Dock 栏、设置应用名称、处理协议链接等
  • 路径管理: 获取系统定义的各种路径,如用户数据目录、临时文件目录等
  • 应用信息: 获取应用名称、版本号等信息

主要功能和用途

  • 创建和管理浏览器窗口 (BrowserWindow)
  • 监听并响应应用的生命周期事件。
  • 控制应用的菜单、Dock 栏、任务栏等
  • 处理应用的启动参数和协议
  • 管理应用的基本信息和设置

核心 API 详解

生命周期事件

app 模块通过触发一系列事件来让您有机会响应应用程序状态的变化

  • ready: 当 Electron 完成初始化时触发。这是创建浏览器窗口等操作最安全的时机。也可以使用 app.whenReady(),它返回一个 Promise,在应用就绪时 resolve
  • window-all-closed: 当所有的窗口都被关闭时触发
  • before-quit: 在应用程序开始关闭窗口之前触发。可以通过 event.preventDefault() 来阻止应用退出
  • will-quit: 在所有窗口都已关闭,应用即将退出时触发。同样可以通过 event.preventDefault() 阻止退出
  • quit: 在应用退出时触发
  • activate (macOS): 当应用被激活时触发,例如点击 Dock 图标

示例:

js
const { app, BrowserWindow } = require("electron")
 
app.on("ready", () => {
  const win = new BrowserWindow()
  win.loadFile("index.html")
})
 
app.on("window-all-closed", () => {
  // 在 macOS 上,除非用户用 Cmd + Q 确定退出,
  // 否则应用在没有窗口的情况下仍会保持活跃。
  if (process.platform !== "darwin") {
    app.quit()
  }
})
 
app.on("before-quit", (event) => {
  // 在这里可以执行一些清理工作,例如保存用户数据
  // 如果有未完成的任务,可以阻止应用退出
  if (hasUnsavedChanges) {
    event.preventDefault()
    // 提示用户保存
  }
})
 
app.on("activate", () => {
  // 在 macOS 上,当点击 Dock 图标并且没有其他窗口打开时,
  // 通常在应用程序中重新创建一个窗口。
  if (BrowserWindow.getAllWindows().length === 0) {
    createWindow()
  }
})

应用程序控制方法

  • app.quit(): 尝试关闭所有窗口并退出应用程序

  • app.exit(exitCode): 强制退出应用,exitCode 默认为 0。这会立即终止应用,不会触发 before-quitwill-quit 事件

  • app.relaunch(): 重新启动当前应用

  • app.focus(): 在 Windows 和 macOS 上,将应用程序的第一个窗口置于前台

  • app.hide() (macOS): 隐藏所有应用窗口

  • app.show() (macOS): 显示所有被隐藏的应用窗口

路径管理

  • app.getPath(name): 获取与 name 关联的系统目录或文件的路径。常用的 name 包括:

    • home: 用户的主目录
    • appData: 当前用户的应用数据目录
    • userData: 存储应用配置文件的目录
    • temp: 临时文件夹
    • desktop: 当前用户的桌面目录
    • documents: "我的文档" 目录
    • downloads: 下载目录
    • exe: 当前可执行文件的路径
    • module: libchromiumcontent 库的路径
    javascript
    const path = require("path")
    const dbPath = path.join(app.getPath("userData"), "user-data.db")
  • app.setPath(name, path): 设置 name 对应的路径。只能在 ready 事件触发前调用

其他重要方法

  • app.getName(): 获取当前应用的名称
  • app.setName(name): 设置当前应用的名称
  • app.getVersion(): 获取应用的版本号
  • app.getLocale(): 获取当前应用的语言环境
  • app.isReady(): 返回一个布尔值,判断 ready 事件是否已触发
  • app.addRecentDocument(path) (Windows & macOS): 将路径添加到最近使用的文档列表中
  • app.clearRecentDocuments() (Windows & macOS): 清空最近使用的文档列表

使用示例

基础初始化代码

这是一个典型的 Electron 主进程文件 (main.js) 的结构:

javascript
const { app, BrowserWindow } = require("electron")
const path = require("path")
 
function createWindow() {
  const mainWindow = new BrowserWindow({
    width: 800,
    height: 600,
    webPreferences: {
      preload: path.join(__dirname, "preload.js")
    }
  })
 
  mainWindow.loadFile("index.html")
}
 
app.whenReady().then(() => {
  createWindow()
 
  app.on("activate", () => {
    if (BrowserWindow.getAllWindows().length === 0) {
      createWindow()
    }
  })
})
 
app.on("window-all-closed", () => {
  if (process.platform !== "darwin") {
    app.quit()
  }
})

处理单例应用

确保应用只有一个实例在运行

javascript
const gotTheLock = app.requestSingleInstanceLock()
 
if (!gotTheLock) {
  app.quit()
} else {
  app.on("second-instance", (event, commandLine, workingDirectory) => {
    // 当运行第二个实例时,聚焦到主窗口
    if (myWindow) {
      if (myWindow.isMinimized()) myWindow.restore()
      myWindow.focus()
    }
  })
 
  // ... 创建窗口等
}

注意事项

平台差异

  • window-all-closed: 在 macOS (darwin) 上,关闭所有窗口通常不会退出应用。应用会保持在 Dock 栏中,直到用户显式退出 (Cmd + Q)
  • activate: 这个事件只在 macOS 上触发
  • 菜单和 Dock/任务栏: 不同平台有不同的 UI 约定,需要为不同平台编写特定的代码来处理

常见问题解决方案

  • API 在 ready 事件前调用: 大多数 app 模块的 API 只能在 ready 事件触发后使用。如果过早调用,可能会导致错误或无效果
  • 黑屏/白屏: 如果在 ready 事件后没有正确创建窗口或加载内容,应用可能会显示一个空白窗口。确保窗口创建和内容加载逻辑正确

性能优化建议

  • 延迟加载模块: 只有在需要时才 require 模块,可以加快应用的启动速度
  • 使用 whenReady(): 相比于 on('ready', ...)app.whenReady() 提供了更现代的 Promise-based API,代码更清晰

相关模块链接

  • BrowserWindow: 创建和控制应用窗口
  • ipcMain: 在主进程和渲染进程之间进行异步通信
  • Menu: 创建原生应用菜单和上下文菜单
  • dialog: 显示用于打开/保存文件、警告等的原生系统对话框