electron+vue3渲染进程与主进程通信

需求:用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();
  }
});
相关推荐
LuciferHuang4 小时前
震惊!三万star开源项目竟有致命Bug?
前端·javascript·debug
GISer_Jing4 小时前
前端实习总结——案例与大纲
前端·javascript
天天进步20154 小时前
前端工程化:Webpack从入门到精通
前端·webpack·node.js
姑苏洛言5 小时前
编写产品需求文档:黄历日历小程序
前端·javascript·后端
知识分享小能手6 小时前
Vue3 学习教程,从入门到精通,使用 VSCode 开发 Vue3 的详细指南(3)
前端·javascript·vue.js·学习·前端框架·vue·vue3
姑苏洛言6 小时前
搭建一款结合传统黄历功能的日历小程序
前端·javascript·后端
你的人类朋友7 小时前
🤔什么时候用BFF架构?
前端·javascript·后端
知识分享小能手7 小时前
Bootstrap 5学习教程,从入门到精通,Bootstrap 5 表单验证语法知识点及案例代码(34)
前端·javascript·学习·typescript·bootstrap·html·css3
一只小灿灿7 小时前
前端计算机视觉:使用 OpenCV.js 在浏览器中实现图像处理
前端·opencv·计算机视觉