前言
主进程和渲染进程通过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配置问题,目前还没解决,有什么好办法呢?