首先简单的理解一下Electron的进程类型——渲染进程和主进程
主进程: Electron 运行 package.json 的 main 脚本的进程。
渲染进程: 在 web 页面运行的进程。
一个 Electron 应用有且只有一个主进程。
主进程中运行的脚本通过创建web页面来展示用户界面。 每个 Electron 中的 web 页面运行在它自己的渲染进程中。
主进程管理所有的web页面和它们对应的渲染进程。 每个渲染进程都是独立的,它只关心它所运行的 web 页面。
主进程和渲染进程可以相互通信。 如 可以使用ipcRenderer 和 ipcMain模块发送消息,可以使用 remote模块进行 RPC(远程过程调用)方式通信。
在我的vue-electron-demo项目中,package.json的main脚本是 background.js:
一、利用remote模块,让主进程、渲染进程通信;
直接在渲染进程里调函数:
注意:
项目中装了Element和sass
利用remote模块,在渲染进程中使用主进程模块。利用remote 模块,可以调用 主进程对象的方法, 而不必显式发送进程间消息。具体用法参考:官网
remote.getCurrentWindow()返回的是 BrowserWindow -即 此网页所属的窗口,它和主进程的win 相同,即主进程中的 new BrowserWindow ( {....} )
header.vue
文件:
<template><div class="header"><span class="el-icon-minus" @click="minimizeWin"></span><span class="el-icon-full-screen" @click="maximizeWin"></span><span class="el-icon-close" @click="closeWin"></span></div></template><script>import { remote } from 'electron';export default {methods: {minimizeWin(){remote.getCurrentWindow().minimize(); // 窗口最小化},maximizeWin(){const win=remote.getCurrentWindow();if(win.isMaximized()){ // 判断 窗口是否已最大化 win.restore();// 恢复原窗口大小}else{win.maximize(); //最大化窗口}},closeWin(){remote.getCurrentWindow().close(); // 关闭窗口,也结束了所有进程}}}</script><style lang="scss">.header{span{font-size:20px;margin-right:20px;color:red;}}</style>
图标 效果如下(此时已具备最小化、最大化、恢复以及关闭当前窗口的功能):
二、使用ipcRenderer
和ipcMain
模块发送消息,让主进程、渲染进程通信;
在渲染进程给主进程发消息,通知主进程我要进行什么操作
注意:
在渲染进程中通过ipcRender
模块给主进程发送信息;主进程中接收渲染进程的消息,并调用函数,进行相应的操作。
<template><div class="header"><span class="el-icon-minus" @click="minimizeWin"></span><span class="el-icon-full-screen" @click="maximizeWin"></span><span class="el-icon-close" @click="closeWin"></span></div></template><script>const ipcRenderer = require('electron').ipcRenderer;export default {methods: {minimizeWin(){ipcRenderer.send('window-min') // 通知主进程我要进行窗口最小化操作},maximizeWin(){ipcRenderer.send('window-max')},closeWin(){ipcRenderer.send('window-close')}}}</script><style lang="scss">.header{span{font-size:20px;margin-right:20px;color:red;}}</style>
在background.js
文件:中新增如下代码:
async function createWindow() {createMenu();// Create the browser window.win = new BrowserWindow({width: 1300,height: 660,minWidth: 1300,useContentSize: true,resizable: true,frame: false,//通过设置frame的值为false可以隐藏窗口的边框。// backgroundColor: '#DC143C',// titleBarStyle: 'hidden',webPreferences: {webSecurity: false, //Remove cross domain restrictionsnodeIntegration: process.env.ELECTRON_NODE_INTEGRATION,// eslint-disable-next-line no-undefpreload: `${__static}/preload.js`},//${__ Static} corresponds to the public directory// eslint-disable-next-line no-undeficon: `${__static}/img/icons/logo-64.png`// icon: `${__static}/img/icons/favicon.ico`});if (process.platform === 'darwin') {// eslint-disable-next-line no-undefapp.dock.setIcon(`${__static}/img/icons/logo-512.png`);}if (process.env.WEBPACK_DEV_SERVER_URL) {// Load the url of the dev server if in development modeawait win.loadURL(process.env.WEBPACK_DEV_SERVER_URL);/* if (!process.env.IS_TEST) win.webContents.openDevTools(); */} else {createProtocol('app');// Load the index.html when not in developmentwin.loadURL('app://./index.html');//Detect version updates// updateHandle(win, feedUrl);}win.on('closed', () => {win = null;});globalShortcut.register('CommandOrControl+Shift+i', function () {win.webContents.openDevTools();});// esc,globalShortcut.register('ESC', function () {win.unmaximize();});// 新增三块 1 2 3; win是 win = new BrowserWindow({......})来的。// 1. 窗口 最小化ipcMain.on('window-min',function(){ // 收到渲染进程的窗口最小化操作的通知,并调用窗口最小化函数,执行该操作win.minimize();})// 2. 窗口 最大化、恢复ipcMain.on('window-max',function () {if(win.isMaximized()){ // 为true表示窗口已最大化win.restore();// 将窗口恢复为之前的状态.}else{win.maximize();}})// 3. 关闭窗口ipcMain.on('window-close',function (){win.close();})}
注意:
我使用的electron版本是11.2.1,在渲染进程中引入
constipcRenderer=require('electron').ipcRenderer;
会出现报错:
解决方法是在根目录的vue.config.js文件中添加:
module.exports = {pluginOptions: {electronBuilder: {nodeIntegration: true}}}
即可解决这个问题。
最后附上electron无边框配置:
1. 无边框窗口实现
通过设置frame的值为false可以隐藏窗口的边框。
win = new BrowserWindow({
frame: false,
});
mac上的红绿灯
实现了无边框后,通过设置titleBarStyle属性,可以在mac上保留红绿灯,titleBarStyle的值可选:
default:默认,标准灰色不透明的mac标题栏;
hidden : 全尺寸内容窗口,保留标准的控制按钮;
hiddenInset :控制按钮距离边框更大;
customButtonsOnHover:鼠标划过左上角的时候显示(官方文档显示该属性在实验中);
win = new BrowserWindow({
frame: false,
titleBarStyle: 'hidden',
});
窗口可拖拽
在需要拖拽的位置设置样式-webkit-app-region: drag; 即可拖拽。(官方文档中提到drag属性会影响到点击事件,所以在点击区域需要设置no-drag,但是在mac上试了下不设置no-drag,单击双击貌似没什么问题,还不知道原因)。
-webkit-app-region: drag;
注:设置可拖拽属性的时候影响到开发者工具,如果把开发者工具和应用显示在同一窗口,会使窗口无法拖拽,这个时候最好让developer tool独立显示。参考文章:【electron】- 无边框窗口应用中的一些坑