超详细!!!electron-vite-vue开发桌面应用之创建新窗口以及主进程和子进程的通信监听(十二)
云风网
云风笔记
云风知识库
一、新建打开窗口
1、在electron/main.ts中加入主进程打开窗口逻辑代码
import { ipcMain } from "electron";
ipcMain.handle("open-win", (_, arg) => {
const childWindow = new BrowserWindow({
webPreferences: {
preload:path.join(__dirname, 'preload.mjs'),
nodeIntegration: true,
contextIsolation: false,
},
});
childWindow.loadFile(path.join(RENDERER_DIST, 'index.html'),{
hash: arg
});
});
2、在electron/preload.ts中定义ipcRenderer全局方法
import { ipcRenderer } from 'electron'
window.ipcRenderer = ipcRenderer
3、在src/utils下新建electron.ts封装打开窗口的公共方法
/**
* 新建窗口
* @param path 路由地址
*/
export function openWindow(path: string) {
window.ipcRenderer.invoke("open-win", path);
}
export default {
openWindow
};
4、在前端文件中应用打开新的窗口
<script setup lang="ts">
const router = useRouter()
import electronUtils from "@/utils/electron";
const toUser = () => {
router.push('/userManage')
}
const toNote = () => {
router.push('/func/noteManage')
}
const toLogin = () => {
router.push('/login')
}
const toOpenLogin = () => {
electronUtils.openWindow('/login');
}
</script>
<template>
<div class="container">
<a @click="toUser()">用户管理</a>
<a @click="toNote()">语录管理</a>
<a @click="toLogin()">去登录</a>
<a @click="toOpenLogin()">创建新窗口</a>
</div>
</template>
二、主进程和子进程的通信
electron项目常常由一个主进程和多个渲染进程构成,渲染进程之间是隔离的,而所有渲染进程都和主进程共享资源。
- 所有的渲染进程都是由主进程创建的
- 每个窗口都对应着一个渲染进程
- 所有的渲染进程共享一个主进程
- 渲染进程与渲染进程交互【多窗口交互】,都需要借助ipc通信来实现
2.1、子进程向主进程单向通信
1、在electron目录下创建ipc.ts
import { ipcMain } from "electron";
export const initIpc = () => {
// 同步通信监听
ipcMain.on("eventSync", (e, data: string) => {
setTimeout(() => {
e.returnValue = "主进程同步响应:" + data;
}, 1000);
});
// 异步通信监听
ipcMain.handle("eventAsync", (e, data: string) => {
return "主进程异步响应:" + data;
});
// 异步通信一次
ipcMain.handleOnce("eventAsyncOnce", (e) => {
console.log("异步通信一次!",e);
});
};
2、在main.ts引入初始化
import {initIpc} from './ipc'
//初始化initIpc
initIpc()
3、在用户管理新增用户详情编辑子路由
{
path: '/',
component: Layout,
hidden: false,
redirect: 'noredirect',
children: [
...
{
path: 'userManage/detail',
component: () => import('@/views/userManage/detail.vue'),
name: 'detail',
meta: { title: '用户详情', icon: 'user' },
hidden: true
}
]
}
4、在src/views/userManage下新建detail.vue
<script setup lang="ts">
import { ipcRenderer } from "electron";
function toSyncSaveUserInfo() {
const result = ipcRenderer.sendSync("eventSync", "同步保存");// 同步通信测试
console.log(result);
}
function toAsyncSaveUserInfo() {
const result = ipcRenderer.invoke("eventAsync", "异步保存");// 异步通信测试
console.log(result);
}
function toAsyncOnceSaveUserInfo() {
const result = ipcRenderer.invoke("eventAsyncOnce", "异步保存一次");// 异步通信测试一次
console.log(result);
}
</script>
<template>
<a @click="toSyncSaveUserInfo()">同步保存</a>
<a @click="toAsyncSaveUserInfo()">异步保存</a>
<a @click="toAsyncOnceSaveUserInfo()">异步保存一次</a>
</template>
<style scoped>
</style>
4、在src/views/userManage/index.vue添加打开编辑用户信息窗口的代码
<script setup lang="ts">
import electronUtils from "@/utils/electron";
const router = useRouter()
const toIndex = () => {
router.push('/')
}
const toNote = () => {
router.push('/func/noteManage')
}
const toEditUserInfo = () => {
electronUtils.openWindow('/userManage/detail');
}
</script>
<template>
<a @click="toIndex()">首页</a>
<a @click="toNote()">语录管理</a>
<a @click="toEditUserInfo()">编辑用户详情</a>
</template>
<style scoped>
</style>
5、点击打开用户详情子窗口进程
点击保存用户信息,子进程向主进程通信
同步保存、异步保存、异步保存一次,其中异步保存一次后主进程移除监听,再次点击保存报错
2.2、主进程向子进程单向通信
1、main.ts定义定时器通信数据给子进程
ipcMain.handle("open-win", (_, arg) => {
const childWindow = new BrowserWindow({
webPreferences: {
preload:path.join(__dirname, 'preload.mjs'),
nodeIntegration: true,
contextIsolation: false,
},
});
let count = 100
setInterval(() => {
if (childWindow&&childWindow.webContents) {
childWindow?.webContents.send("to-child-count", '金额:'+count++);
}
}, 1000);
childWindow.webContents.openDevTools();
childWindow.loadFile(path.join(RENDERER_DIST, 'index.html'),{
hash: arg
});
});
2、detail.vue监听主进程通信数据
// 监听主进程信息
function toChildCount(e:any,data:string){
console.log(data)
}
onMounted(()=>{
ipcRenderer.on("to-child-count",toChildCount);
console.log("监听主进程信息")
});
onUnmounted(()=>{
console.log('移除监听主进程信息')
ipcRenderer.removeListener("to-child-count",toChildCount);
});
2.3、主进程和子进程双向通信
1、electron/ipc.ts添加双向通信逻辑
//双向通信
ipcMain.handle("eventBothWay", (e, data: string) => {
e.sender.send("eventBothWay", "主进程发送" + data);
});
2、detail.vue子进程添加监听逻辑
function eventBothWay(e:any,data:string){
console.log("子进程监听的信息:",data);
}
function toBothWay(){
ipcRenderer.invoke("eventBothWay","异步发给主进程的消息");
}
onMounted(()=>{
ipcRenderer.on("eventBothWay",eventBothWay);
// ipcRenderer.on("to-child-count",toChildCount);
// console.log("监听主进程信息")
});
onUnmounted(()=>{
ipcRenderer.removeListener("eventBothWay",eventBothWay);
// console.log('移除监听主进程信息')
// ipcRenderer.removeListener("to-child-count",toChildCount);
});
<a @click="toBothWay()">双向通信</a>
点击双向通信,可以控制台获取双向信息打印