前言
主進程和渲染進程通過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配置問題,目前還沒解決,有什么好辦法呢?