超详细!!!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项目常常由一个主进程和多个渲染进程构成,渲染进程之间是隔离的,而所有渲染进程都和主进程共享资源。

  1. 所有的渲染进程都是由主进程创建的
  2. 每个窗口都对应着一个渲染进程
  3. 所有的渲染进程共享一个主进程
  4. 渲染进程与渲染进程交互【多窗口交互】,都需要借助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>

点击双向通信,可以控制台获取双向信息打印

在这里插入图片描述

### 配置 Electron Vite 的多窗口 在 Electron Vite 结合的项目中实现多窗口功能,可以通过以下方式完成。以下是详细的说明以及示例代码。 #### 创建主进程文件 `main.js` 并初始化多个窗口 通过监听事件触发新窗口创建逻辑。可以利用 `BrowserWindow` 来管理不同的窗口实例[^1]。 ```javascript const { app, BrowserWindow } = require('electron'); let mainWindow; let secondaryWindow; function createMainWindow() { mainWindow = new BrowserWindow({ width: 800, height: 600, webPreferences: { preload: path.join(__dirname, 'preload.js'), contextIsolation: true, }, }); // 加载Vite开发服务器中的HTML页面 mainWindow.loadURL(`http://localhost:3000/index-electron.html`); } function createSecondaryWindow() { secondaryWindow = new BrowserWindow({ width: 600, height: 400, parent: mainWindow, modal: false, webPreferences: { preload: path.join(__dirname, 'preload.js'), contextIsolation: true, }, }); // 加载另一个HTML页面作为子窗口的内容 secondaryWindow.loadFile('./dist/index-secondary.html'); } app.whenReady().then(() => { createMainWindow(); // 监听打开新窗口的事件 ipcMain.on('open-second-window', () => { createSecondaryWindow(); }); }); ``` #### 前端部分:发送消息给主进程以请求开启新的窗口 可以在前端通过 IPC 向主进程发送信号来启动第二个窗口[^2]。 ```javascript // 在 index-electron.html 或对应的 Vue 组件中引入此脚本 const { ipcRenderer } = require('electron'); document.getElementById('open-new-window').addEventListener('click', () => { ipcRenderer.send('open-second-window'); // 发送事件通知主进程 }); ``` #### 构建 HTML 文件支持多窗口场景 对于每个独立运行的窗口都需要有自己的入口 HTML 文件。例如: - 主窗口使用的是由 Vite 提供的服务地址 (`http://localhost:3000/index-electron.html`)- 子窗口则可以直接加载本地构建后的静态资源 (如上述例子中的 './dist/index-secondary.html')。 确保这些 HTML 文件都已正确定义并能够被正确访问。 --- ### 示例总结 以上展示了如何在一个基于 Electron Vite 的应用里设置两个相互关联却各自独立运作的 GUI 窗口。主要涉及到了以下几个方面: 1. **主进程中定义不同类型的浏览器窗口**; 2. **前后端交互机制——IPC通信**; 3. **针对各个窗口准备相应的HTML模板**; 这使得开发者可以根据实际需求灵活扩展应用程序的功能界面布局。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

niech_cn

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值