api系列
Electron模块
app
app 模块,它控制应用程序的事件生命周期。
whenReady
当electron应用加载准备好时候进行处理
app模块的ready事件被激发后才能创建浏览器窗口。app.whenReady()API来监听此事件
quit
app.quit退出应用程序
注意退出应用程序,需要区分window和mac
isPackaged
app.isPackaged
- 返回一个
boolean值,如果应用已经打包,返回true,否则返回false。 对于大多数应用程序,此属性可用于区分开发和生产环境
BrowserWindow
BrowserWindow 模块,它创建和管理应用程序窗口。
- 窗口模块
常用配置
- width、height: 窗口大小
- alwaysOnTop : 窗口置顶
- x、y : 窗口位置
- 一般不直接写死,通过判断当前屏幕分辨率,来动态设置x、y
- show: 设置窗口是否在创建时显示
- skipTaskbar: 是否在任务栏中显示窗口,默认false
const win = new BrowserWindow({
width: 800,
height: 600,
webPreferences: {
nodeIntegration: true,
contextIsolation: false,
},
});
// 加载网页
// win.loadURL('https:www.baidu.com');
// 加载文件
win.loadFile('index.html');
webContents
主要在主进程中使用,当然也可以传递参数给预加载脚本去操作
webContent 渲染进程中的网页内容, 可以控制网页的内容对象 【可以理解 当前窗口的网页内容对象】
- toggleDevTools: 切换开发者工具
- send: 发送事件消息
- on:接收事件消息
- title: 设置当前网页窗口标题
// 切换开发者工具
win.webContents.toggleDevTools();
// 接收事件消息
win.webContents.on('test')
// 发送事件消息
win.webContents.send('test',{age:'20'})
setWindowOpenHandler
setWindowOpenHandler 是一个用于控制新窗口打开行为的方法。通过该方法,你可以自定义在点击链接或调用 window.open() 函数时如何处理新窗口
使用场景:
- 阻止新窗口被打开
- 在应用内部打开新窗口
// 设置新窗口打开处理函数
win.webContents.setWindowOpenHandler(({ url }) => {
// 在主窗口中打开新链接
// 1、mainWindow.loadURL(url);
shell.openExternal(url)
return { action: 'deny' }; // 阻止默认行为
});
webPreferences
webPreferences设置网页的偏好
- nodeIntegration: 集成node, 可以在渲染进程/预加载脚本中使用node模块
- contextIsolation: 控制渲染进程 是否为沙箱模式 【控制是否隔离模式】
- 默认情况下,渲染进程、预加载脚本、主进程都是隔离的
- 设置false,表示开启不隔离模式
- preload: 预加载脚本
- sandbox: 控制沙箱模式
注意如果contextIsolation设置为false、nodeIntegration设置为true,那么安全性会大大降低。建议按默认就行
fromWebContents
简单理解 为获取当前网页窗口对象
- 用于从一个现有的
WebContents对象获取对应的BrowserWindow对象 - 可用于主线程和渲染进程 互相通信
// 主进程和渲染进程互相通信
ipcMain.on('my-channel', (event, args) => {
// event.sender 表示发送消息的渲染进程的 WebContents 对象。
const webContents = event.sender;
// 从 webContents 对象中获取关联的 BrowserWindow 对象
const win = BrowserWindow.fromWebContents(webContents);
win.send('msg', '已经收到通知');
});
// 在渲染进程/预加载脚本
ipcRenderer.on('msg', (event, message) => {
console.log('message', message);
});
事件
- ready-to-show :窗口准备好后时候触发 【确保窗口已经准备好】
// 在窗口准备好后设置标题
win.once('ready-to-show', () => {
win.setTitle('标题');
});
方法
setBounds/setSize调整窗口大小
进程间通信模块
ipc: interprocess communication 进程间通信
ipcMain 和 ipcRenderer 都是 EventEmitter 类的⼀个实例。EventEmitter 类是 NodeJS 事件 的基础,它由 NodeJS 中的 events 模块导出。
EventEmitter 的核⼼就是事件触发与事件监听器功能的封装。
- 它实现了事件模型需要的接⼝, 包括 addListener,removeListener, emit 及其它⼯具⽅法. 同原⽣ JavaScript 事件类似, 采 ⽤了发布/订阅(观察者)的 ⽅式,
ipcMain和ipcRenderer
用于主线程和渲染进程通信
IpcMain
- IpcMain在主进程使用时,可以处理渲染进程(页面) 发送出来的消息 (包括异步和同步消息)
- 也可以在主进程向渲染进程发送消息
- 主进程通过
ipcMain.on来接受事件
ipcRenderer
- 渲染进程通过
ipcRenderer.send来发送消息 - 也可以在预加载脚本 通过
ipcRenderer.send来发送消息 【安全性】 - 主进程也可以通过拿到win通过
webContents.send来发送消息,渲染进程通过ipcRender.on来接收
例子:
- ipcRenderer.send 发送消息,然后使用 ipcMain.on 接收
// main.js
// 主进程和渲染进程通信
ipcMain.on('my-channel', (event, args) => {
console.log(event, 'event');
console.log(args, 'agrs');
});
// index.html
const { ipcRenderer } = require('electron');
function onSendMain() {
ipcRenderer.send('my-channel', {
name: 'this is electron',
});
}
ipcRenderer.invoke 与 ipcMain.handle 双向通信
- preload.js 预加载脚本
- 预加载脚本中,使用
contextBridge.exportInMainWorld来暴露api方法,提供给渲染进程使用 - 可以有效的控制主进程的api可以被渲染进程使用
- 预加载脚本中,使用
- 使用ipcRenderer.invoke 与 ipcMain.handle 双向通信,可以从渲染器进程代码调用主进程模块并等待结果
contextBridge.exportInMainWorld('api',{
upload:async()=>{
const file = await ipcRenderer.invoke('selectFile')
return file
}
})
- main.js 主进程
ipcMain.handle('selectFile',async()=>{
const { filePaths } = await dislog.showOpenDialog()
return filePaths[0]
})
事件相关的信息
ipcMain 模块用于在主进程中监听和处理与渲染进程之间的事件通信。当在主进程中接收到来自渲染进程的事件时,ipcMain 会传递一个事件对象(通常是 event)作为参数给回调函数,这个事件对象包含了与事件相关的信息
-
event.sender
-
返回
WebContents对象,表示触发事件的渲染进程的网页内容 -
可以使用它来向渲染进程发送回复通信消息
-
可以使用它从网页对象来获取当前渲染进程窗口对象
const win = BrowserWindow.fromWebContents(event.sender);
-
-
event.reply()
-
event.reply 是一个用于向渲染进程发送消息的方法
-
方法用于向触发事件的渲染进程发送回复。它可以传递回复事件的名称和数据
-
-
event.preventDefault()
- 可用于阻止默认行为,通常在事件处理程序中用于防止某些默认操作
- 如阻止默认打开文件对话框行为
- 可用于阻止默认行为,通常在事件处理程序中用于防止某些默认操作
contextBridge
注意,主线程BrowserWindow窗口对象 选项中不要设置contextIsolation为false, 否则无法使用contextBridge,需要确保contextIsolation为true, 这样可以将渲染进程隔离开,才能使用contextBridge桥接方式进行通信 【这种机制可以有效地防止渲染进程与主进程之间的直接访问,从而保护应用程序的安全性】
在隔离的上下文中创建安全、双向、同步的桥接
- 用于在渲染进程和主进程之间建立安全的通信
- 可以控制哪些主进程的 API 可以被渲染进程访问 【通过exposeInMainWorld】
- 这样可以避免恶意代码通过直接访问主进程引发安全风险。
contexdtBridge可以理解为 在渲染进程和主进程 在隔离的上下文环境中,建议安全的通信
使用场景
- 用于在预加载脚本中
- 如预加载脚本定义 访问主进程的方法api
- 在预加载脚本 使用contextBridge.exposeInMainWorld在方法api暴露给渲染进程
exposeInMainWorld
- contextBridge.exposeInMainWorld(apiKey, api)
- 将api暴露给渲染进程,渲染进程通过window对象来访问api
- 渲染进程可以通过window.myAPI来访问的
// 主进程的预加载脚本
const { contextBridge,ipcRenderer } = require('electron');
// 定义主进程中可被访问的 API
const api = {
getInfo: (callback) => {
// 执行一些操作
// 接收事件
ipcRenderer.on('info',(event,value)=>{
callback(value)
})
}
};
// 将 API 暴露给渲染进程
contextBridge.exposeInMainWorld('myAPI', api);
screen模块
screen 模块用于获取有关计算机屏幕的信息以及与屏幕相关的操作。它提供了一种方法来检测和管理显示器、获取屏幕的分辨率、屏幕大小、获取鼠标的位置等等
使用场景
- 屏幕截图
- 摄像头
- 鼠标位置追踪
常用的api
- screen.getAllDisplays()
- 返回一个数组,其中包含所有连接到计算机的显示器的信息,每个元素都是一个显示器对象
- screen.getPrimaryDisplay()
- 返回显示器的信息,可以从中获取宽高度
- screen.getCursorScreenPoint()
- 返回鼠标当前位置的坐标点
例子:
ipcMain.on('updateSize', (event, options) => {
// 获取当前显示器 工作区域的大小
const { width, height } = screen.getPrimaryDisplay().workAreaSize;
const win = BrowserWindow.fromWebContents(event.sender);
const x = width / 2 - options.width / 2;
const y = height / 2 - options.height / 2;
win.setBounds({ ...options, x, y }, true);
});
shell
注意: 虽然
shell模块可以在渲染进程中使用,但在沙盒渲染进程中无法使用
shell 模块是用于提供与操作系统本地 shell 相关功能的模块。允许你执行各种与文件系统、外部程序和默认应用相关的操作。
使用场景
- 打开外部链接:你可以使用 shell 模块的
openExternal(url)方法打开外部链接,这将在用户的默认浏览器中打开指定的 URL。这在你想在用户系统中打开一个网页链接时非常有用。 - 打开文件或目录:你可以使用 shell 模块的
openItem(fullPath)或showItemInFolder(fullPath)方法,分别用于在系统中打开指定文件或目录,这将在文件资源管理器中显示文件或目录。这在你想让用户通过你的应用访问特定文件或目录时非常有用。 - 执行外部程序:你可以使用 shell 模块的
openPath(fullPath)方法执行外部程序并将文件作为参数传递给它。这在你想通过你的应用打开特定类型的文件时非常有用,例如使用系统默认的图片编辑程序打开一张图片
基本使用:
// 打开外部链接
shell.openExternal(url)
remote
remote 模块为渲染进程和主进程通信提供了⼀种简单⽅法。 在Electron中, GUI 相关的模块 (如 dialog、menu 等) 仅在主进程中可以, 在渲染进程中不可用。 为了在渲染进程中使用它们, ipc 模块是向主进程发送进程间消息所必需的。 使用 remote 模块, 你可以调用 main 进程对象的方法, 而不必显式发送进程间消息
- 通过remote模块,可以简化 渲染进程和主进程之间的通信
注意
remote模块在 Electron 12 废弃,并将在 Electron 14 被移除. 由@electronic/remote模块替代
缺点
- 很慢
- 通过remote模块可以访问主进程的对象、类型、方法,但这些操作都是跨进程的
- 跨进程操作性能上的损耗可能是进程内操作的几百倍甚至上千倍
系统托盘
托盘:Tray
- 添加图标和上下文菜单到系统通知区
注意平台差异
window:
- 建议使用
ICO图标获取最佳视觉效果。 - 应用图标可以是彩色
macOS:
-
应用图标是黑白色
-
图标必须是 图片模板
-
确保文件名没有被破坏或哈希。 文件名需要以 Template 单词结尾,同时
@2x图片需要与标准图片文件名相同,否则 MacOS 不会神奇地反转图片的颜色或使用高分图片 -
为了确保您的图标在视网膜监视器不模糊,请确认你的
@2x图片是 144dpi 。
基本使用
import { app } from 'electron'
import { Tray, Menu, MenuItemConstructorOptions, MenuItem } from 'electron'
import path from 'path'
// 创建系统托盘
const createTray = () => {
const iconPath = path.resolve(
__dirname,
process.platform === 'darwin'
? '../../resources/macCameraTemplate.png'
: '../../resources/windowCamera.png'
)
const tray = new Tray(iconPath)
const menuTemplate: Array<MenuItemConstructorOptions | MenuItem> = [
{
label: '退出',
click: () => app.quit()
}
]
const contextMenu = Menu.buildFromTemplate(menuTemplate)
tray.setToolTip('摄像头软件')
tray.setContextMenu(contextMenu)
}
export default createTray
通知 Notifications
组件模块
electron内置了一些组件模块,比如菜单、弹窗等
Menu 菜单管理
1、针对不同平台,设置不同菜单项
2、设置菜单分割线、通过类型type为separator
3、设置快捷键,通过accelerator
4、设置菜单事件等
用于创建和管理应用程序菜单的核心模块组件
- buildFromTemplate
- 从模板对象来创建菜单
- 包含菜单标签、子菜单、快捷键、事件函数等
- setApplicationMenu
- 设置应用的菜单,用于把菜单显示到菜单上
Menu模块还提供其他方法来操作菜单,例如append、insert、popup等
const { Menu } = require('electron');
// 需要传递win窗口对象,让菜单知道操作哪个窗口 【因为有很多个渲染进程窗口的】
const createMenu = (win) => {
const memu = [
{
label: '菜单',
submenu: [
{
label: '设置',
accelerator: process.platform === 'darwin' ? 'Cmd+O' : 'Shift+O', // 定义快捷键
click: () => {
// 拿到win对象,就可以向渲染进程进行通信了
console.log('win.webContents', win.webContents);
win.webContents.send('info','信息')
},
},
],
},
];
Menu.setApplicationMenu(Menu.buildFromTemplate(memu));
};
module.exports = {
createMenu,
};
Menu.popup实现右键菜单
配合Menu.popup实现右键菜单功能
- 在预加载脚本中,定义监听右键菜单,向主进程发送事件
// 监听右键菜单
window.addEventListener('contextmenu', () => {
ipcRenderer.send('popMenu');
});
- 在主进程中接收
const { ipcMain, app, Menu, BrowserWindow } = require('electron');
const createPopMenu = () => {
ipcMain.on('popMenu', (event, value) => {
const template = [
{
label: '退出',
click: () => app.quit(),
},
];
const menu = Menu.buildFromTemplate(template);
menu.popup({
window: BrowserWindow.fromWebContents(event.sender),
});
});
};
module.exports = {
createPopMenu,
};
使用场景
- 应用程序菜单
- 创建和管理应用程序的主菜单和上下文菜单(右键菜单)。你可以定义菜单项,子菜单,快捷键以及与菜单项相关联的事件处理程序。
- 自定义菜单栏
- 允许你在应用程序窗口的顶部创建自定义菜单栏,类似于传统的桌面应用程序。这可以让你的应用程序看起来更加专业和一致
dialog模块
用于创建本地操作系统原生的对话框,以便与用户进行交互。这些对话框可用于各种场景,例如打开文件、保存文件、选择文件夹、显示警告消息、弹出框等
常见使用场景:
- 打开文件对话框:用于让用户选择一个或多个文件以供应用程序使用。通常用于文件的导入或打开操作。
- 保存文件对话框:用于指定文件的保存位置和名称,以便将应用程序中的数据保存到文件中。
- 选择文件夹对话框:用于让用户选择一个文件夹,以便应用程序可以在指定位置创建文件或保存文件。
- 消息框:用于显示警告、错误、信息或询问用户是否继续执行某个操作的消息。
- 错误框:用于显示错误消息和异常情况,通常与进程错误处理相关。
- 自定义对话框:您可以使用
dialog模块创建自定义对话框,以满足特定应用程序的需求。
常用 API:
-
dialog.showOpenDialog([browserWindow, ]options):显示一个打开文件对话框,用户可以选择一个或多个文件。options参数允许您配置对话框的行为,例如指定默认目录、文件类型过滤等。 -
dialog.showSaveDialog([browserWindow, ]options):显示一个保存文件对话框,用户可以选择文件的保存位置和名称。 -
dialog.showMessageBox([browserWindow, ]options):显示一个消息框,用于显示信息、警告或询问用户是否继续执行某个操作。您可以指定消息的类型、按钮和图标。 -
dialog.showErrorBox(title, content):显示一个错误框,用于显示错误消息。通常用于处理应用程序的异常情况。 -
dialog.showOpenDialogSync([browserWindow, ]options)和dialog.showSaveDialogSync([browserWindow, ]options):这是同步版本的文件对话框,它们会阻塞主线程,直到用户完成操作。但请注意,使用同步对话框可能会导致应用程序在对话框打开时无响应,因此在主进程之外的地方调用它们更为安全。 -
dialog.showMessageBoxSync([browserWindow, ]options)和dialog.showErrorBoxSync(title, content):这是同步版本的消息框,它们也会阻塞主线程。 -
dialog.showOpenDialogBrowser(options)和dialog.showSaveDialogBrowser(options):这是用于打开文件和保存文件的浏览器风格的文件对话框,可以与渲染进程一起使用。注意,这些方法只在渲染进程中可用。 -
dialog.showMessageBoxBrowser(options):用于在渲染进程中显示消息框。
Electron dialog和<input type="file />区别
- 复杂交互:Electron 的对话框dialog是系统级别的文件操作,可以与系统交互做更复杂的操作
- 跨平台性: Electron的对话框dialog可以跨平台