什么是 electron
electron是使用JavaScript,HTMl和CSS构建的跨平台的桌面应用。
很多应用都在使用electron,比如VSCode、GitHub Desktop等。
主进程与渲染进程
主进程:
- 可以使用和系统对接的Electron API 创建菜单,上传文件等
- 创建渲染进程
- 全面支持Node.js
- 只有一个,作为程序的入口点
渲染进程:
- 可以有多个,每个对应一个窗口
- 每个都是一个单独的进程
- 全面支持Node.js和DOM API
- 可以使用一部分Electron提供的API
主进程
在package.json
文件中main
属性对应的main.js
文件就是主进程。
在main.js
中我们可以创建渲染进程:通过使用BrowserWindow
API来创建窗口,这个API只能在主进程中使用:
const { app, BrowserWindow } = require('electron');
// BrowerWindow负责创建窗口,只能在main.js中使用。
app.on('ready', () => {
// 创建主窗口
const mainWindow = new BrowserWindow({
width: 800,
height: 600,
webPreferences: {
nodeIntegration: true// 可以使用node的API
}
});
mainWindow.loadFile('index.html'); // 加载index.html文件
// 创建渲染窗口
const secondWindow = new BrowserWindow({
width: 400,
height: 400,
webPreferences: {
nodeIntegration: true// 可以使用node的API
},
parent:mainWindow
});
secondWindow.loadFile('second.html');// 加载second.html文件
})
其中的index.html
、second.html
里面的内容可自行定义。
渲染进程
我们在index.html
文件中引入了renderer.js
文件,这就是渲染进程。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<h1>Hello world </h1>
<script>
require('./renderer.js')
</script>
</body>
</html>
渲染进程renderer.js
中全面支持Node.js和DOM API:
// renderer.js
// 即支持node API也支持DOM API
alert(process.versions.node);
window.addEventListener('DOMContentLoaded', () =>{
alert('greeting from the DOM side');
})
nodemon
一般的,我们执行上面的代码时,是这样的:运行npm start
就可以启动electron .
命令。
但是缺点是每一次更新main.js
之后,就要重新运行npm start
,很不方便。
我们可以下一个辅助工具nodemon
,它可以监听main.js
的变化,当主进程变化时,可以自动运行上面的命令,不用重启。修改上面的代码:监听main.js
的变化,如果有变化,就重新启动electron .
命令。
代码效果
进程之间的通信
主进程与渲染进程之间通过IPC
来保持通信。
- 首先,修改上面的
main.js
,我们只创建一个主窗口:
const { app, BrowserWindow} = require('electron');
// BrowerWindow负责创建窗口,只能在main.js中使用。
app.on('ready', () => {
// 创建主窗口
const mainWindow = new BrowserWindow({
width: 800,
height: 600,
webPreferences: {
nodeIntegration: true// 可以使用node的API
}
});
mainWindow.loadFile('index.html'); // 加载index.html文件
})
- 渲染进程向主进程发消息。
修改renderer.js
中的代码,引入ipcRenderer
模块,基于它来向主进程发消息:
const {ipcRenderer} = require('electron');
window.addEventListener('DOMContentLoaded', () =>{
// 发送数据
ipcRenderer.send('message', 'hi mainProcess');
})
修改main.js
中的代码,来接受渲染进程的消息。引入ipcMain
模块,基于它来监听来自渲染进程的消息:
const { app, BrowserWindow, ipcMain } = require('electron');
// BrowerWindow负责创建窗口,只能在main.js中使用。
app.on('ready', () => {
// 创建主窗口
const mainWindow = new BrowserWindow({
width: 800,
height: 600,
webPreferences: {
nodeIntegration: true// 可以使用node的API
}
});
mainWindow.loadFile('index.html'); // 加载index.html文件
// 监听渲染进程发送的数据
ipcMain.on('message', (event, data) => {
console.log(data);
})
})
上面的代码中data
就是来自渲染进程的数据。更新main.js后可以看到渲染进程发送的消息:hi mainProcess
- 主进程向渲染进程发消息:
在上面的代码中更新以下内容:通过event.sender
的send
方法将渲染进程发消息
// 监听渲染进程发送的数据
ipcMain.on('message', (event, data) => {
console.log(data);
// event.sender表示事件的发送者,通过send方法再把主进程要发送的数据
// 发送回去。
event.sender.send('reply', 'i am from mainProcess');
// 也可以写成:
// mainWindow.send('reply', 'i am from mainProcess')
})
更新renderer.js
的内容:监听来自主进程的数据。
const {ipcRenderer} = require('electron');
window.addEventListener('DOMContentLoaded', () =>{
// 发送数据
ipcRenderer.send('message', 'hi i am from rendererProcess');
// 监听数据
ipcRenderer.on('reply', (event, data) => {
document.getElementById('message').innerHTML = data;
})
})
更新index.html
,在其中加一个<p>
标签,id
为 message
。
<h1>Hello world </h1>
<p id="message"> </p>
<script>
require('./renderer.js')
</script>
结果如下,来自主进程的i am from mainProcess
数据显示在窗口中: