设置你的项目
初始化npm项目
Electron 应用使用 npm 搭建脚手架,并以 package.json 文件作为入口点。首先创建一个文件夹并在其中使用 npm init 初始化一个 npm 包。
zsh
mkdir my-electron-app && cd my-electron-app
npm init
此命令将提示你配置 package.json 中的一些字段。出于本教程的目的,需要遵循一些规则:
-
入口点应该是
main.js(你很快就会创建该文件)。 -
作者、许可证和描述可以是任何值,但稍后对于 packaging 是必需的。
然后,将 Electron 安装到应用的 devDependency 中,这是生产中不需要的外部仅开发包依赖的列表。
为什么 Electron 是一个 devDependency?
这可能看起来违反直觉,因为你的生产代码正在运行 Electron API。然而,打包的应用将与 Electron 二进制文件打包在一起,从而无需将其指定为生产依赖。
zsh
npm install electron --save-dev
初始化包并安装 Electron 后,你的 package.json 文件应如下所示。你现在还应该有一个包含 Electron 可执行文件的 node_modules 文件夹,以及指定要安装的确切依赖版本的 package-lock.json 锁定文件。
json
{
"name": "my-electron-app",
"version": "1.0.0",
"description": "Hello World!",
"main": "main.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"author": "Jane Doe",
"license": "MIT",
"devDependencies": {
"electron": "23.1.3"
}
}
如果直接安装 Electron 失败,请参阅我们的 高级安装 文档,了解有关下载镜像、代理和故障排除步骤的说明。
添加 .gitignore
.gitignore 文件指定要避免使用 Git 跟踪的文件和目录。你应该将 GitHub 的 Node.js gitignore 模板 的副本放入项目的根文件夹中,以避免提交项目的 node_modules 文件夹。
运行Electron应用
阅读 Electron 的进程模型 文档以更好地理解 Electron 的多个进程如何协同工作。
你在 package.json 中定义的 main 脚本是任何 Electron 应用的入口点。该脚本控制主进程,该进程在 Node.js 环境中运行,负责控制应用的生命周期、显示原生界面、执行特权操作以及管理渲染器进程(稍后会详细介绍)。
在创建第一个 Electron 应用之前,你将首先使用一个简单的脚本来确保主进程入口点配置正确。使用一行代码在项目的根文件夹中创建 main.js 文件:
js
console.log('Hello from Electron 👋')
由于 Electron 的主进程是 Node.js 运行时,因此你可以使用 electron 命令执行任意 Node.js 代码(你甚至可以将其用作 REPL)。要执行此脚本,请将 electron . 添加到 package.json 的 scripts 字段中的 start 命令中。该命令将告诉 Electron 可执行文件在当前目录中查找主脚本并在开发模式下运行它。
package.json
json
{
"name": "my-electron-app",
"version": "1.0.0",
"description": "Hello World!",
"main": "main.js",
"scripts": {
"start": "electron .",
"test": "echo \"Error: no test specified\" && exit 1"
},
"author": "Jane Doe",
"license": "MIT",
"devDependencies": {
"electron": "23.1.3"
}
}
zsh
npm run start
你的终端应该打印出 Hello from Electron 👋。恭喜,你已经在 Electron 中执行了第一行代码!接下来,你将学习如何使用 HTML 创建用户界面并将其加载到原生窗口中。
将网页加载到 BrowserWindow 中
Electron 中,每个窗口都显示一个网页,可以从本地 HTML 文件或远程网址加载。对于本示例,你将加载本地文件。首先在项目根文件夹中的 index.html 文件中创建一个准系统网页:
html
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<!-- https://web.nodejs.cn/en-US/docs/Web/HTTP/CSP -->
<meta
http-equiv="Content-Security-Policy"
content="default-src 'self'; script-src 'self'"
/>
<meta
http-equiv="X-Content-Security-Policy"
content="default-src 'self'; script-src 'self'"
/>
<title>Hello from Electron renderer!</title>
</head>
<body>
<h1>Hello from Electron renderer!</h1>
<p>👋</p>
</body>
</html>
现在你已经有了一个网页,你可以将其加载到 Electron BrowserWindow 中。将 main.js 文件的内容替换为以下代码。我们将分别解释每个高亮的块。
js
const { app, BrowserWindow } = require('electron')
const createWindow = () => {
const win = new BrowserWindow({
width: 800,
height: 600
})
win.loadFile('index.html')
}
app.whenReady().then(() => {
createWindow()
})
导入模块
js
const { app, BrowserWindow } = require('electron')
在第一行中,我们使用 CommonJS 模块语法导入两个 Electron 模块:
-
app,它控制应用的事件生命周期。
-
BrowserWindow,创建和管理应用窗口。
编写可重用函数来实例化窗口
createWindow() 函数将你的网页加载到新的 BrowserWindow 实例中:
main.js (Lines 3-10)
js
const createWindow = () => { const win = new BrowserWindow({ width: 800, height: 600 }) win.loadFile('index.html')}
当应用准备就绪时调用你的函数
main.js (Lines 12-14)
app.whenReady().then(() => { createWindow()})
Electron 的许多核心模块都是 Node.js 事件触发器,遵循 Node 的异步事件驱动架构。应用模块就是这些触发器之一。
在 Electron 中,只有在应用模块的 ready 事件被触发后才能创建 BrowserWindows。你可以使用 app.whenReady() API 等待此事件,并在其 promise 履行后调用 createWindow()。
此时,运行 Electron 应用的 start 命令应该成功打开一个显示网页的窗口!
你的应用在窗口中显示的每个网页都将在称为渲染器进程(或简称为渲染器)的单独进程中运行。渲染器进程可以访问与典型前端 Web 开发相同的 JavaScript API 和工具,例如使用 webpack 打包和缩小代码或使用 React 构建用户界面。
管理应用的窗口生命周期
应用窗口在每个操作系统上的行为有所不同。如果你希望遵循这些约定,Electron 不会默认强制执行这些约定,而是让你可以选择在应用代码中实现它们。你可以通过监听应用和 BrowserWindow 模块发出的事件来实现基本的窗口约定。
所有窗口关闭后退出应用(Windows 和 Linux)
在 Windows 和 Linux 上,关闭所有窗口通常会完全退出应用。要在你的 Electron 应用中实现此模式,请监听应用模块的 window-all-closed 事件,并在用户不在 macOS 上时调用 app.quit() 退出你的应用。
app.on('window-all-closed', () => { if (process.platform !== 'darwin') app.quit()})
如果没有打开窗口,则打开一个窗口 (macOS)
相比之下,macOS 应用通常即使没有打开任何窗口也会继续运行。在没有可用窗口时激活应用应该会打开一个新窗口。
要实现此功能,请监听应用模块的 activate 事件,并在没有打开 BrowserWindows 的情况下调用现有的 createWindow() 方法。
由于无法在 ready 事件之前创建窗口,因此你应该仅在应用初始化后监听 activate 事件。通过仅监听现有 whenReady() 回调中的激活事件来执行此操作。
js
app.whenReady().then(() => {
createWindow()
app.on('activate', () => {
if (BrowserWindow.getAllWindows().length === 0) createWindow()
})
})
最终的起始代码
main.js
js
const { app, BrowserWindow } = require('electron/main')
const createWindow = () => {
const win = new BrowserWindow({
width: 800,
height: 600
})
win.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()
}
})
index.html
html
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<meta
http-equiv="Content-Security-Policy"
content="default-src 'self'; script-src 'self'"
/>
<meta
http-equiv="X-Content-Security-Policy"
content="default-src 'self'; script-src 'self'"
/>
<title>Hello from Electron renderer!</title>
</head>
<body>
<h1>Hello from Electron renderer!</h1>
<p>👋</p>
<p id="info"></p>
</body>
<script src="./renderer.js"></script>
</html>