electron项目常常由一个主进程和多个渲染进程构成,渲染进程之间是隔离的,而所有渲染进程都和主进程共享资源。
我们主进程与渲染进程交互,渲染进程与渲染进程交互【多窗口交互】,都需要借助ipc通信来实现
封装加载进度显示,新建窗口 演示主进程与渲染进程通信
demo项目地址
官方ipc进程通信讲解教程
electron官方文档ipc通信
方向 | 主进程【ipcMain】 | 渲染进程【ipcRenderer】 |
---|---|---|
渲染=>主 【同步/异步】 | ipcMain.on() | ipcRender.send() / ipcRender.sendSync() 【同步取值】 |
渲染=>主 【异步】 | ipcMain.handle() | ipcRender.invoke() |
主=>渲染 【异步】 | BrowserWindow【实例】.webContents.send() | ipcRender.on() |
1.我们创建一个ipc测试文件,ipcDemo.ts
import { ipcMain } from "electron";
export const initIpcDemo = () => {
// 同步处理通信,并等待主进程返回值
ipcMain.on("event-on-test", (e, data: string) => {
setTimeout(() => {
e.returnValue = "主进程同步响应:" + data;
}, 2000);
});
// 异步处理通信,异步返回结果
ipcMain.handle("event-handle-test", (e, data: string) => {
return "主进程异步响应:" + data;
});
// 异步处理一次
ipcMain.handleOnce("event-handleOnce-test", (e) => {
console.log("异步通信处理一次!");
});
};
2.接着我们在electron的入口文件中引入
import {initIpcDemo} from './ipcDemo'
// 初始化ipc通信Demo
initIpcDemo();
3.我们创建一个ipcDemo的.vue文件,测试渲染进程=>主进程的单向通信:
<template>
<div>
<go-back>go-back>
<ul>
<li><el-button @click="eventOnTest">同步通信测试el-button>li>
<li><el-button @click="eventHandleTest">异步通信测试el-button>li>
<li><el-button @click="eventHandleOnceTest">异步通信一次el-button>li>
ul>
div>
template>
<script setup lang="ts">
import { ipcRenderer } from "electron";
import { onMounted, onUnmounted } from "vue";
// 同步通信测试
function eventOnTest() {
const result = ipcRenderer.sendSync("event-on-test", "狼来了");
console.log(result);
}
// 异步通信测试
function eventHandleTest() {
ipcRenderer.invoke("event-handle-test", "小龙你好").then((res) => {
console.log(res);
});
}
// 异步通信一次
function eventHandleOnceTest() {
ipcRenderer.invoke("event-handleOnce-test");
}
script>
<style scoped lang="scss">style>
4.补充对应的页面路由后,我们看一下测试结果
1.我们在主窗口初始化完毕的地方补充代码逻辑,创建一个定时器每隔两秒向渲染进程发送消息
let number = 1;
setInterval(() => {
if (win && win.webContents) {
win.webContents.send("event-from-main", "计数" + number++);
}
}, 2000);
2.渲染进程补充监听:
+src\components\demo\ipcDemo.vue
<script setup lang="ts">
onMounted(()=>{
ipcRenderer.on("event-from-main",eventFromMain);
});
// 来自主进程的消息
function eventFromMain(e:any,data:string){
console.log("监听到消息",data)
}
onUnmounted(()=>{
ipcRenderer.removeListener("event-from-main",eventFromMain);
});
script>
按官方文档来看,主进程handle并return,渲染进程用promise语法,或主进程on并e.returnValue,渲染进程用sendSync就是双向通信
这里我个人认为多窗口间的双向通信适合用下面的写法,上面的写法在渲染进程=>主进程中已经演示,故不赘述,这里主要演示下下面的使用
1.主进程补充逻辑,在收到渲染进程的调用后,主动给渲染进程的窗口发送消息
import { ipcMain } from "electron";
export const initIpcDemo = () => {
// 双向通信处理
ipcMain.handle("event-handle-togeter-test", (e, data: string) => {
e.sender.send("event-handle-togeter-test", "主进程通知" + data);
});
};
2.测试代码补充逻辑
<template>
<div>
<ul>
<li>
<el-button @click="eventHandleTogeterTestClick">双向通信el-button>
li>
ul>
div>
template>
<script setup lang="ts">
import { ipcRenderer } from "electron";
import { onMounted, onUnmounted } from "vue";
onMounted(()=>{
ipcRenderer.on("event-handle-togeter-test",eventHandleTogeterTest);
});
function eventHandleTogeterTestClick(){
ipcRenderer.invoke("event-handle-togeter-test","奥利给");
}
// 双向通信测试
function eventHandleTogeterTest(e:any,data:string) {
console.log("渲染进程监听到:",data);
}
onUnmounted(()=>{
ipcRenderer.removeListener("event-handle-togeter-test",eventHandleTogeterTest);
});
script>
<style scoped lang="scss">style>