项目模版
对于electron无论是webpack、vite都需要分别对main、preload、renderer进行打包并和chromium、node api生成对应平台应用
- electron-forge : 通过其插件系统提供了项目环境、打包分发、包发布、等完整流程,并且具有webpack、vite两种构建可以选择
- electron-vite : 以vite为构建方案的不同框架模版
核心api
main-process
主进程主要提供作用到操作系统的api及事件,通常位于main工程目录下
- app : 包含了主应用程序事件触发及监听
ts
app.on('window-all-closed', () => {
app.quit();
})
- BrowserWindow : 主应用窗口相关(配置、页面渲染、调试工具、窗口事及监听)
- 一个应用可以存在多个窗口但需要指明父级窗口
ts
function createWindow() {
mainWIndow = new BrowserWindow({ /* ... */ })
secondaryWindow = new BrowserWindow({
// ...,
modal: false, // 是否以modal形式展示
show: false, // modal为true时生效
parent: mainWindow
});
}
- webContents : 作为
BrowserWindow的属性(对应的配置也将反映到属性当中)用于响应和控制web页面的事件触发及监听- mainWindow.webContents
ts
const wc = mmainWindow.webContents;
wc.on('did-finish-load', () => {})
wc.on('dom-ready', () => {})
wc.on('focus', () => {})
// ...
- Accelerator : 用于监听组合快捷键
ts
globalShortcut.register('CommandOrControl+Shift+Alt+C', () => {
app.focus();
browserWindow.show();
browserWindow.focus();
});
- Menu : 菜单相关配置(Menu、MenuItem、context-menu)
ts
const mainMenu = new Menu();
const menuItem = new MenuIitem({ label: 'File': subMenu: [/**/] })
mainMenu.append(menuItem)
Menu.setApplicationMenu(mainMenu)
const contextMenu = Menu.buildFromTemplate({ label: 'xxx', subMenu: [/**/]})
mainWindow.webContents.on('context-menu', e => contextMenu.popup())
- Tray : 系统托盘图标菜单配置
ts
const someTray = new Tray('xxx/xxx/icon.png')
someTray.setToolTip('hover tip text')
someTray.on('click', e => {
// do something
})
- screen : 屏幕相关事件及方法(尺寸、显示、光标位置)
ts
const [dp1, dp2] = screen.getAllDisplays()
console.log(`
primary monitor: ${dp1.size.width}x${dp1.size.height}\n
srcondary monitor: ${dp2.size.width}x${dp2.size.height}`
)
screen.on('display-metrics-changed', (e, display, metricsChanged) => {
console.log(metricsChanged)
})
renderer-process
渲染进程主要包含mainwindow中渲染的web相关页面及资源,通常位于renderer工程目录下.新版本不能直接在渲染进程中使用必须通过preload桥接
- clipboard : 系统粘贴板相关
- contextBridge : 通过
ipcRenderer通信暴露桥接主线程与渲染线程的事件,通常位于preload中 - crashRepoeter : 自动提交崩溃报告到远端服务器
- ipcRenderer : 用于主进程和渲染进程之间监听和派发约定事件
- webFrame : 用于自定义渲染当前的web页面(zooom、insertCSS、insetText、executeJavascript、...)
- desktopCapturer : 桌面音视频捕捉
ipcinter-process-communication
<Primary>IPC</Primary>主要用于ipcMain和ipcRenderer之间的通信
- Renderer to main : 渲染进程到主进程,出了
send > on这种通用订阅方式还有invoke > handle的异步返回方式
ts
import { contextBridge, ipcMain, ipcRenderer } from "electron"
// main.ts
ipcMain.on('someContent', (e, content: string) => console.log(content))
ipcMain.handle('otherContent', async (e, content: string) => dealWithContent(content))
// preload.ts
contextBridge.exposeInMainWorld('app', {
sendToMain: (content: string) => {
ipcRenderer.send('someContent', content)
},
otherToMain: async (content: stirng) => {
const result = await ipcRenderer.invoke('otherContent')
return result
}
})
// renderer/index.ts
document.getElementById('dom1').onclick = () => {
window.app.sendToMain()
}
document.getElementById('dom2').onclick = () => {
window.app.otherToMain()
}
- Main to renderer : 主进程到渲染进程除了
send > on以外的webContents方式
ts
import { BrowserWindow, ipcMain, ipcRenderer } from "electron"
// main.ts
const mainWindow = new BrowserWindow(/* ... */)
Menu.buildFromTemplate([
{
label: 'xxx'
subMenu: [
{
label: 'xxx',
click: () => mainWindow.webContents.send('updateSomething', 'xxx')
},
// ...
]
}
])
// preload.ts
// 这里可以不暴露到renderer中,直接定义在preload中
window.addEventListener('DOMContentLoaded', () => {
const contentDom = document.getElementById('dom')
ipcRenderer.on('updateSomthing', (_event, content) => {
contentDom.innerText = content
})
})
// index.html
<body>
<div id="dom">/* ... */</div>
</body>
<script type="module" src="renderer/index.ts">
shared-modules
- process : 包含了可以在主、渲染进程中访问使用的属性、方法、事件
- shell : 包含了与桌面集成相关的功能(
openPath、showItemInFolder、...,不同操作系统的表现也不相同) - nativeImage : 图片相关api可以通过本机路径、nativeImage实例创建并包含很多图片实例方法(
toPNG、toJPEG、toDataURL、...) - clipboard : 粘贴板相关功能
扩展功能
- Offsreen Rendering : 使用禁止硬件加速开启离屏渲染(不渲染页面的情况下进行逻辑处理)
ts
import { app, BrowserWindow } from "electron"
app.disableHardwareAcceleration()
const mainWindow = new BrowserWindow({
show: false,
webPreferences: {
nodeIntegration: true,
offscreen: true
}
}})
mainWindow.loadURL('https://electronjs.org')
let i = 1
mainWindow.webContents.on('paint', (e, dirty, image) => {
fs.writeFile(app.getPath('desktop') + `/screenshot_${i}`, image.toPNG(), console.log)
i++;
})
mainWindow.webContents.on('did-finish-load', () => {
// ...
})
- Network Detection : 网络状况监测
- Notification : 消息通知
- autoUpdater : 自动更新应用