背景
网上讲Electron进程通信的就很少了,直接现成讲结合Vue的更是屈指可数,而且很多资料非常老旧。
环境
- Electron 29.1.4
- Vue 3.4.21
基本流程
Electron主流的做法是和前端通讯前经过预加载preload脚本,而不是直接和前端交互,这是出于安全的考虑。
主程序(main.js)↔预加载脚本(preload.js)↔前端(例如Vue.app / HTML)
在Vue的环境下,如果再通过渲染器调用预加载脚本,然后Vue页面再调用渲染器(render.js)的方式,一方面是比较麻烦,而且我觉得没有充分利用好Vue的特性。
双向通信的代码实现
*两种单向通信大致原理相同,但不是采用invoke的方法,可以参看Electron的官方教程
- 主程序(main.js)添加监听
const { app, BrowserWindow, ipcMain} = require('electron/main') // 记得导入ipcMain async function <你自定义的handle处理函数> () { // 在这里写你的处理函数,记得写return返回,返回的结果会给前端 } app.whenReady().then(() => { // 在窗口准备好后开始准备监听 ipcMain.handle('<你的通道名称>', <你自定义的handle处理函数>) // 监听预加载脚本的<你的通道名称>通道,被前端调用了就执行<你自定义的handle处理函数>,并且返回处理完的返回值。 // ...创建窗口的代码,此处省略。... })
- 预加载脚本(preload.js)暴露API
const { contextBridge, ipcRenderer } = require('electron') contextBridge.exposeInMainWorld('<自定义暴露的API名称>', { <你的方法名称>: () => ipcRenderer.invoke('<你的通道名称>') })
- Vue直接调用被暴露的接口
<template> <div> HelloWorld! <button @click="<点击调用的方法名>">Click</button> <div>{{ var2 }}</div> </div> </template> <script> export default { name: 'App', data: function(){ return { var2: "" } }, methods:{ async <点击调用的方法名>(){ const var1 = await window.<暴露的API名称>.<你的方法名称>() // 执行你在main.js定义的handle处理函数,并且把返回值传递给var1 this.var2 = var1 // 把接收到的传给Vue中的var2 } } } </script>