前言
主进程和渲染进程通过IPC进行通信,每次需要定义名称并注册,很多代码都是重复书写,并且如果主进程和渲染进程开发人员是同一个的话,很多东西都可以简化。
渲染进程通过ipcRenderer.invoke与主进程通信,主进程通过ipcMain.handle接受渲染进程传递的参数并返回调用结果,二者用一个key进行对应,希望此过程可以简化,省略key的书写,进行自动注册。
主进程
使用electron-vite脚手架创建electron项目,在主进程文件夹中创建ipc文件夹,ipc文件夹中包含一个index文件和一个handlers文件夹,在handlers文件夹中放入所有的处理函数,并用index导出。
| -- main
| -- ipc
| -- handlers
| -- xxx1.js
| -- xxx2.js
| -- index.js
| -- index.js
| -- index.js
| -- preload
| -- index.js
例如,在xxx1.js中有一个处理函数
// xxx1.js
import process from "node:process"
export const getEnv = ()=>{
return JSON.stringify(processa.env)
}
在handlers的index文件中导出
import { getEnv } from './xxx1'
export {
getEnv
}
在ipc的index中对所有的handler进行自动注册,并注册一个getIpcHandlerForPreload方便在preload中进行调用
import { ipcMain } from 'electron'
import * as handlers from './handlers'
export const registerHandlerForIpcMain = () => {
for (const key in handlers) {
const handler = handlers[key];
ipcMain.handle(key, (_event, ...params) => handler(...params));
}
ipcMain.handle("getIpcHandlerForPreload", () => Object.keys(handlers));
};
在主进程的入口index处调用这个函数
import {registerHandlerForMainAndPreload } from "./ipc/index.js";
...
app.whenReady().then(() => {
registerHandlerForMainAndPreload();
...
});
preload
在preload中对渲染进程要使用的invoke进行处理,把接口暴露给渲染进程
import { contextBridge, ipcRenderer } from 'electron'
import { electronAPI } from '@electron-toolkit/preload'
import { platform } from 'os';
// Custom APIs for renderer
const api = {
currentPlatform: platform()
}
// Use `contextBridge` APIs to expose Electron APIs to
// renderer only if context isolation is enabled, otherwise
// just add to the DOM global.
if (process.contextIsolated) {
try {
contextBridge.exposeInMainWorld('electron', electronAPI);
contextBridge.exposeInMainWorld('api', api);
(async () => {
const ipcMainHandlers = await ipcRenderer.invoke('getIpcHandlerForPreload');
const electronAPIContent = {};
for (const handlerName of ipcMainHandlers) {
electronAPIContent[handlerName] = function() { return ipcRenderer.invoke(handlerName, ...arguments); };
}
contextBridge.exposeInMainWorld('ipcInvoke', electronAPIContent);
})();
} catch (error) {
console.error(error)
}
} else {
// @ts-ignore (define in dts)
window.electron = electronAPI
// @ts-ignore (define in dts)
window.api = api
}
渲染进程
最后,在渲染进程中就可以直接通过preload暴露的接口使用函数了,参数也可以直接传递,不需要第一个参数是event。
// 渲染进程中xxx.js
window.ipcInvoke.getEnv()
问题
本来想在ipc的index中使用动态引入handlers文件夹中的东西,但是打包后路径会报错,找不到handlers文件夹,应该是vite配置问题,目前还没解决,有什么好办法呢?