背景
Electron 依赖 Chromium 的更新迭代,很多功能用法都在不断地变更
比如我在 bilibili 学习 Electron入门到精通(有可能是全站最好的electron课程) 的时候,发现网上的教程清一色都是使用 remote 进行进程间通信
而 Electron 早在 14 版本就移除了 remote 模块,官方推荐的方法是使用 ipcMain 和 ipcRender 进行进程间通信(详细请看官方文档)
虽然也有办法继续使用 remote 模块,但这显然不是一个长久之计。所以咱们最好还是学着用 ipcMain 和 ipcRender
进程通信
可以参考上述官方文档,实现进程间简单的消息的发送和接受
那么该如何实现点击按钮创建一个新窗口的目的呢?很简单
思路之一是,在主进程的 main.js 中预编写一段可以与其它进程通信的代码,当收到其它进程的特定通信内容时,咱们就执行这段代码,创建一个新窗口,就跟上一篇创建 Hello World 的主窗口是一样的~
这里写了一个点击主界面中的设置按钮,打开设置窗口,再点击一次关闭设置窗口的 Demo,各部分代码如下
main.js
const { app, BrowserWindow, ipcMain } = require('electron')
// 主进程需使用 ipcMain ↑
const createWindow = () => {
const win = new BrowserWindow({
width: 800,
height: 600,
autoHideMenuBar: true, // 隐藏菜单栏
webPreferences: {
nodeIntegration: true,
contextIsolation: false
}
})
win.loadFile('./html/index.html')
}
const controlSettingsWindow = () => {
if (!settingsWin) {
settingsWin = new BrowserWindow({
width: 500,
height: 300,
autoHideMenuBar: true, // 隐藏菜单栏
webPreferences: {
nodeIntegration: true,
contextIsolation: false
}
});
settingsWin.loadFile('./settings.html'); // 加载 settings.html
} else {
settingsWin.destroy(); // 再次点击时关闭该窗口
settingsWin = null;
}
}
// 进程间通信开始↓
// 创建设置窗口(settings)
let settingsWin = null;
ipcMain.on('settings-window', () => {
controlSettingsWindow(); // 调用设置窗口创建和关闭的函数
});
// 进程间通信结束↑
app.whenReady().then(() => {
createWindow()
app.on('activate', () => {
if (BrowserWindow.getAllWindows().length === 0) {
createWindow()
}
})
})
app.on('window-all-closed', () => {
if (process.platform !== 'darwin') {
app.quit()
}
})
index.html
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<meta
http-equiv="Content-Security-Policy"
content="default-src 'self'; script-src 'self'"
/>
<meta
http-equiv="X-Content-Security-Policy"
content="default-src 'self'; script-src 'self'"
/>
<title>Electron Test Demo</title>
</head>
<body>
<h1>👋你好啊</h1>
<button id="open-settings-btn">点击打开设置窗口</button>
<script src="./index.js"></script>
<p id="info"></p>
</body>
</html>
index.js
const { ipcRenderer } = require('electron')
// 子进程(渲染进程)中使用 ipcRender
window.addEventListener('DOMContentLoaded', () => {
const sBtn = document.getElementById('open-settings-btn')
sBtn.addEventListener('click', () => {
// 调用主进程中,预编写的函数实现打开窗口
ipcRenderer.send('settings-window');
})
})
settings.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>设置页面 | Electron Test Demo</title>
</head>
<body>
<h1>这里是设置页面~</h1>
<script src="./settings.js"></script>
</body>
</html>
settings.js
const { ipcRenderer } = require('electron')
window.addEventListener('DOMContentLoaded', () => {
// 拦截点击该窗口关闭按钮执行的动作
window.onbeforeunload = function () {
ipcRenderer.send('settings-window');
// 由主进程 main.js 进行该窗口的 destroy() 关闭操作,否则会因为该窗口不为 null 而无法进行第二次打开窗口的操作
}
})
写在结尾
因为我也是刚开始学 Electron 编写桌面端应用,且我并不擅长 JavaScript,所以关于这个 Demo 如果你有更好的方式方法,欢迎留言告诉我~