需求:用electron+vue3开发一个桌面应用,要做一个自定义导航,如何与主进程之间通信呢
项目当中要使用自定义导航,有关闭、放大、还原功能,如何实现呢 electron定义的窗口了导航,如 下图:

如何不显示这个导航呢,使用BrowserWindow实例的frame
来控制,frame设置为false
js
//主进程 background.js
new BrowserWindow({
width: 800,
height: 600,
minWidth: 500,
minHeight: 500,
frame: false, // 去掉electron自带的导航,包括 logo, 最大,最小,关闭图标
autoHideMenuBar: true,
webPreferences: {
nodeIntegration: true, ////是否开启在渲染进程中node的环境
contextIsolation: true, //关闭独立加载electron API
preload: path.join(__dirname, "./preload.js"),
},
});
我们定义好导航,用isMaximized变量
来控制最大化图标与还原图标:
代码:
js
// globalTopBar.vue
<template>
<el-row class="container">
<div>
<el-icon><IceTea /></el-icon>
<span>一个好听的名字</span>
</div>
<div>
<el-icon @click="iconClick('minus')" title="最小化"><Minus /></el-icon>
<el-icon @click="iconClick('plus')" :title="isMaximized ? '还原' : '最大化'"> <CopyDocument v-if="isMaximized" /><Plus v-else /> </el-icon>
<el-icon @click="iconClick('close')" title="关闭" class="close-icon"><Close /></el-icon>
</div>
</el-row>
</template>
<script setup>
import { ref, onBeforeMount, onMounted, onBeforeUpdate, onUpdated, onBeforeUnmount, onUnmounted } from "vue";
const isMaximized = ref(false);
const iconClick = (type) => {};
</script>
<style lang="less" scoped>
.container {
background: #a9a9a9;
color: #fff;
justify-content: space-between;
.el-icon {
vertical-align: middle;
font-size: 20px;
padding: 10px;
cursor: pointer;
&:hover {
background-color: #bdbdbd;
}
}
.close-icon {
&:hover {
background-color: tomato;
}
}
}
</style>
vue页面的点击事件,如关闭、最大化、最小化事件如何传递给主进程
,主进程的事件又如何告知渲染进程
,可以使用预加载脚本preload.js
js
//preload.js
const { contextBridge, ipcRenderer } = require("electron");
contextBridge.exposeInMainWorld("ipcRenderer", {
//渲染进程->主进程
send: (channel, data) => {
let validChannels = ["topIcon"]; // <-- Array of all ipcRenderer Channels used in the client
if (validChannels.includes(channel)) {
ipcRenderer.send(channel, data);
}
},
// 主进程->渲染进程
receive: (channel, func) => {
let validChannels = ["set-maxminicon"]; // <-- Array of all ipcMain Channels used in the electron
if (validChannels.includes(channel)) {
ipcRenderer.on(channel, (event, ...args) => {
func(...args);
});
}
},
});
再将导航文件修改一下,加上事件处理逻辑
js
// globalTopBar.vue
<template>
<el-row class="container">
<div>
<el-icon><IceTea /></el-icon>
<span>一个好听的名字</span>
</div>
<div>
<el-icon @click="iconClick('minus')" title="最小化"><Minus /></el-icon>
<el-icon @click="iconClick('plus')" :title="isMaximized ? '还原' : '最大化'"> <CopyDocument v-if="isMaximized" /><Plus v-else /> </el-icon>
<el-icon @click="iconClick('close')" title="关闭" class="close-icon"><Close /></el-icon>
</div>
</el-row>
</template>
<script setup>
import { ref, onBeforeMount, onMounted, onBeforeUpdate, onUpdated, onBeforeUnmount, onUnmounted } from "vue";
const isMaximized = ref(false);
console.log(window.ipcRenderer);
const ipcRenderer = window.ipcRenderer;
const iconClick = (type) => {
ipcRenderer.send("topIcon", { type });
};
ipcRenderer.receive("set-maxminicon", (args) => {
isMaximized.value = args.max
});
</script>
<style lang="less" scoped>
.container {
background: #a9a9a9;
color: #fff;
justify-content: space-between;
.el-icon {
vertical-align: middle;
font-size: 20px;
padding: 10px;
cursor: pointer;
&:hover {
background-color: #bdbdbd;
}
}
.close-icon {
&:hover {
background-color: tomato;
}
}
}
</style>
别忘记在background.js加载preload
js
//background.js
const { app, BrowserWindow, ipcMain } = require("electron");
const path = require("node:path");
// ctrl+shift+i, 打开调试工具快捷键
function createWindow() {
const win = new BrowserWindow({
width: 800,
height: 600,
minWidth: 500,
minHeight: 500,
frame: false, // 去掉electron自带的导航,包括 logo, 最大,最小,关闭图标
autoHideMenuBar: true,
webPreferences: {
nodeIntegration: true, ////是否开启在渲染进程中node的环境
contextIsolation: true, //关闭独立加载electron API
preload: path.join(__dirname, "./preload.js"),
},
});
win.loadURL("http://localhost:5173/");
return win;
}
app.whenReady().then(() => {
const mainWindow = createWindow();
mainWindow.on("maximize", () => {
console.log("maximize");
mainWindow.webContents.send("set-maxminicon", { max: true });
});
mainWindow.on("unmaximize", () => {
console.log("unmaximize");
mainWindow.webContents.send("set-maxminicon", { max: false });
});
ipcMain.on("topIcon", (event, args) => {
const webContent = event.sender;
const win = BrowserWindow.fromWebContents(webContent);
switch (args.type) {
case "close":
app.quit();
break;
case "minus":
win.minimize();
break;
case "plus":
if (win.isMaximized()) {
win.restore();
} else {
win.maximize();
}
break;
default:
break;
}
});
app.on("activate", () => {
if (BrowserWindow.getAllWindows().length === 0) {
createWindow();
}
});
});
app.on("window-all-closed", () => {
if (process.platform !== "darwin") {
app.quit();
}
});