引入
这里我们通过封装electron的工具类来演示electron中的主进程和渲染进程利用ipc进行通信
【推荐】详细的ipc通信讲解-ipc通信的使用,主进程与渲染进程之间的交互
demo项目地址
electron官方文档ipc通信
实现效果演示:
创建窗口
进度条加载
1.封装新建窗口工具
1.我们首先在electron目录下的main.ts中补充主进程窗口打开代码:
- 如果用的是electron-vite模板工程生成,可以看到104行左右已经给我们创建了一个窗口打开处理器
- 可以看到,这里实际就是让新窗口显示我们路由对应的网站
// electron\main\index.ts
// 【异步通信】 ipcMain.handle 对应 ipcRender.invoke 主进程可直接return,渲染进程接收promise
// 【同步通信】 ipcMain.on 对应 ipcRender.sendSync 主进程 evnet.returnValue =xxx , 渲染进程直接=返回值即可
// 这里接收的第一个参数默认为 事件参数,可以取到发送窗口的一些信息,这里没有用到,所以直接用 _ 占位
ipcMain.handle("open-win", (_, arg) => {
const childWindow = new BrowserWindow({
webPreferences: {
preload,
nodeIntegration: true,
contextIsolation: false,
},
});
if (process.env.VITE_DEV_SERVER_URL) {
childWindow.loadURL(`${url}#${arg}`);
} else {
childWindow.loadFile(indexHtml, { hash: arg });
}
});
2.我们在src目录下新建一个utils目录,然后创建一个electronUtils.ts文件:
import { ipcRenderer } from "electron";
/**
* 新建一个窗口
* @param path 路由地址
*/
export function openWindow(path: string) {
ipcRenderer.invoke("open-win", path);
}
export default {
openWindow,
};
2.测试新建窗口
我们调整 src\components\demo\Index.vue 里的代码:
<template>
<h1>这是demo页 当前计数为:{{ counterStore.counter }}</h1>
<ul>
<li><router-link to="/hello">链接跳转helloworld页</router-link></li>
<li><router-link to="/demo/mockDemo">mockjs案例</router-link></li>
<li><router-link to="/demo/mockApiDemo">前端模拟接口</router-link></li>
<li><router-link to="/demo/sassDemo">sassDemo</router-link></li>
<li>
<el-select
v-model="windowPath"
value-key=""
placeholder="输入路由地址"
clearable
filterable
>
<el-option
v-for="path in routerPaths"
:key="path"
:label="path"
:value="path"
>
</el-option>
</el-select>
<el-button @click="openWindow">新建窗口</el-button>
</li>
</ul>
</template>
<script setup lang="ts">
import { useRouter } from "vue-router";
import { useCounterStore } from "@store/counterStore";
import { ref } from "vue";
import electronUtils from "@/utils/electronUtils";
const counterStore = useCounterStore();
const router = useRouter();
const windowPath = ref("/hello");
const routerPaths = ref<string[]>([]);
// 取到所有的路径
routerPaths.value = router.getRoutes().map((item) => item.path);
function openWindow() {
electronUtils.openWindow(windowPath.value);
}
</script>
<style scoped>
ul {
list-style: none;
}
</style>
测试效果如下:
3.封装进度条加载
1.可以看到官网给了我们一个进度条显示案例:
我们也仿照着在 electron\main\index.ts 中补充代码:
/**
* show : ture 显示app进度条,false,关闭显示
*/
let progressInterval;
ipcMain.handle("show-process", (event, show: boolean) => {
const INCREMENT = 0.03;
const INTERVAL_DELAY = 100; // ms
let c = 0;
if (show) {
progressInterval = setInterval(() => {
win.setProgressBar(c);
if (c < 2) {
c += INCREMENT;
} else {
c = -INCREMENT * 5;
}
}, INTERVAL_DELAY);
} else {
c = 0;
win.setProgressBar(c);
if (progressInterval) {
clearInterval(progressInterval);
}
}
});
2.在src\utils\electronUtils.ts中封装方法,发送消息让主进程执行进度条显示/关闭:
/**
* 显示加载进度条
* @param isShow 是否显示加载进度条【底部工具栏图标显示】
*/
export function showProcess(isShow: boolean) {
ipcRenderer.invoke("show-process", isShow);
}
export default {
showProcess,
};
4.测试进度条加载
我们调整src\components\HelloWorld.vue的代码:
<script setup lang="ts">
import { ref } from "vue";
import electronUtils from "@/utils/electronUtils";
const showProcess = ref(false);
/**切换process 显示/隐藏 */
function switchProcess() {
showProcess.value = !showProcess.value;
electronUtils.showProcess(showProcess.value);
}
</script>
<template>
<ul>
<li>
<el-button type="warning" @click="switchProcess">{{
showProcess ? "关闭process" : "显示process"
}}</el-button>
</li>
</ul>
</template>
<style scoped>
ul {
list-style: none;
}
</style>
测试效果: