Electron 是由两种进程组成的,即主进程和渲染进程
- 在 Electron 里,运行 package.json 里 main 脚本的进程被称为主进程(Main Process),在主进程运行的脚本可以以创建 web 页面的形式展示 GUI:
-
- 主进程通过创建浏览器窗口实例来创建网页:每一个 浏览窗口 实例在其渲染过程中运行网页,当一个 BrowserWindow 实例被摧毁时,对应的渲染过程也被终止
- 主进程管理所有网页及其对应的渲染过程
- 由于 Electron 使用 Chromium 来展示页面,所以 Chromium 的多进程结构也被充分利用:每个 Electron 的页面都在运行着自己的进程,这样的进程我们称之为渲染进程(Renderer Process):
-
- 渲染进程只能管理单个的网页,在一个渲染过程中崩溃不会影响其他渲染过程
- 渲染进程通过 IPC 与主进程通信,在网页上执行 GUI 操作;由于安全考虑和可能的资源泄漏,直接从渲染器过程中调用与本地 GUI 有关的 API 会受到限制## 2 进程 API
针对不同的进程,Electron 提供了不同的 API 以供使用,所以可以分为以下3类 API:
2.1 主进程 API
- app:控制应用的事件生命周期
- autoUpdater:自动更新
- BrowserView:创建和控制视图
- BrowserWindow:创建和控制窗口
- contentTracing:跟踪并确定性能问题
- dialog:创建和控制本机系统对话框
- globalShortcut:监听系统快捷键
- inAppPurchase:(MAC 专用)Mac App Store 的应用内购买
- ipcMain:从主模块到渲染模块的异步通信
- Menu:创建远程应用以及上下文菜单
- MenuItem:在菜单中添加菜单项
- net:发出 HTTP 或 HTTPS 请求
- netLog:记录网络事件
- Notification:创建桌面通知
- powerMonitor:监视电源状态
- powerSaveBlocker:组织系统自动进入省电模式
- protocol:注册自定义协议并拦截基于协议的请求
- screen:检索有关屏幕大小、显示器、光标位置等的信息
- session:管理浏览器会话、cookie、缓存、代理设置等
- systemPreferences:获取系统配置信息
- TouchBar:(MAC 专用)配置 TouchBar 布局
- Tray:添加图标和上下文菜单到系统通知区
- webContents:渲染以及控制 web 页面
2.2 渲染进程 API
- ipcRenderer:从渲染器进程到主进程的异步通信
- remote:在渲染进程中使用主进程模块
- webFrame:自定义渲染当前网页
2.3 通用 API
- desktopCapturer:通过 [navigator.mediaDevices.getUserMedia] API ,可以访问那些用于从桌面上捕获音频和视频的媒体源信息
- clipboard:在系统剪贴板上执行复制和粘贴操作
- crashReporter:将崩溃日志提交给远程服务器
- nativeImage:使用 PNG 或 JPG 文件创建托盘、dock和应用程序图标
- shell:使用默认应用程序管理文件和 url
2.4 示例
例如,要在两个进程中访问 Electron API,需要它包含的模块:
const electron = require('electron');
若要创建一个窗口,请调用 BrowserWindow 模块,它只能在主进程中使用:
const { BrowserWindow } = require('electron');
// 或
import { BrowerWindow} from 'electron';
const win = new BrowserWindow();
若要从渲染器调用主流程,请使用 IPC 模块:
// 在主进程中
const { ipcMain } = require('electron');
// 或
import { ipcMain } from 'electron';
ipcMain.handle('exper-action', (evidence, ...args) =>
// ... 代表渲染器操作
});
// 在渲染进程中
const { ipcRenderer } = require('electron');
// 或
import { ipcRenderer } from 'electron';
ipcRender.invotrake('exper-action', ...args);
注意:由于渲染过程可能会运行不受信任的代码(特别是第三方的代码),重要的是要认真验证主要进程中提出的请求。
如果要从渲染过程中访问 Node.js API,我们需要设置节点集成首选项为 true。
Electron 在主流程和渲染流程中显示对 Node.js API 及其模块的完全访问权限;例如,我们可以从根目录读取所有文件:
const fs = require('fs');
const root = fs.readdirSync('/');
console.log(root);
要使用 Node.js 模块,首先需要安装它作为依赖:
npm install --save aws-sdk
然后,在 Electron 应用程序中,引入模块:
const S3 = require('aws-sdk/clients/s3');
以上是 API 大致使用方式,接下来,就从主进程的几个关键 API 谈起。
3 任务栏、Dock或者桌面启动器自定义
因为一个应用的功能方方面面,所以我们这里主要是通用的东西,在一个操作系统当中,最明显的就是其系统自带功能,所以我们这里可以使用对应的模块,利用到系统自带功能,从而符合对应系统用户对应用的基础使用习惯。
首先就是 Windows 任务栏、Mac Dock 或者 Linux 的桌面启动器。
3.1 Windows 任务栏自定义
首先我们要明确,这里所谓的 Windows 任务栏是特指 Windows 7 之后版本的任务栏,因为一些新的特性是从 Win7 之后才出现。
首先我们来看看,在任务栏的应用图标上右键点击弹出的菜单,比如:
VS Code 的右键菜单,我们自定义的是“任务”这个部分
可以看到,右键点击任务栏中 VS Code 图标后,会弹出一个菜单,其中“任务”这个部分仅有一个命令——新窗口;我们在自己的应用当中也可以定义出这样一个任务菜单项,只需要在 主进程代码中(通常是 main.js 或者 index.js)增加(有基础代码的情况下,基础代码可以参考上一章节):
app.setUserTasks([{
program: process.execPath,
arguments: '--new-window',
iconPath: process.execPath,
iconIndex: 0,
title: '新窗口',
description: '创建新窗口',
}]);
这样在运行应用之后,我们右键点击其图标,就可以看到效果了:
接着是带有缩略图的工具栏,比如:
当然 WMP 现在很少人用了,不过这种工具栏还是很有参考价值的,如果我们开发一个和音视频有关的应用,可能也很想使用这种方式来提供更多的互动,那么可以增加如下内容:
mainWindow.setThumbarButtons([
{
tooltip: 'button1',
icon: path.join(__dirname, 'button1.png'),
click () { console.log('button1 clicked') }
}, {
tooltip: 'button2',
icon: path.join(__dirname, 'button2.png'),
flags: ['enabled', 'dismissonclick'],
click () { console.log('button2 clicked.') }
}
]);
突然发现这个方法有点问题,我直接用官方的方式居然没有按钮……上周因为截图有问题我就没有试过,本身用的也少,居然没发现这个问题……囧一个,我回头看看是不是自己哪里搞错了。
放出一个完整的桌面,大家可以看看,忽略我的MC桌面哈
另外还有我们常见的如果应用失去焦点,但突然获得活动更新了,可以考虑加入图表闪烁的功能,代码也很简单:
mainWindow.once('focus', () => mainWindow.flashFrame(false));
mainWindow.flashFrame(true);
3.2 Mac Dock 自定义
这个例子其实是官网的例子,代码如下:
const dockMenu = Menu.buildFromTemplate([
{
label: 'New Window',
click () { console.log('New Window') }
}, {
label: 'New Window with Settings',
submenu: [
{ label: 'Basic' },
{ label: 'Pro' }
]
},
{ label: 'New Command...' }
])
app.whenReady().then(() => {
app.dock.setMenu(dockMenu)
})
3.3 Linux 桌面启动器自定义
这个其实是围绕着 Linux 桌面的 .desktop 文件来实现的,实际上不能算是直接通过 API 编程实现的,下面是个例子:
Actions=PlayPause;Next;Previous
[Desktop Action PlayPause]
Name=Play-Pause
Exec=audacious -t
[Desktop Action Next]
Name=Next
Exec=audacious -f
[Desktop Action Previous]
Name=Previous
Exec=audacious -r
我今天检查截图才发现了自己上周的有关 ThumbarButton 的实例有问题,见谅哈大家,我回头也查查看是哪里的问题。