一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第8天,点击查看活动详情。
使用Node.js 模块/API
相信用过Node.js的小伙伴来说,对Node中的fs一定不陌生,今天通过读写文件的例子来介绍下electron中的Node.js。
首先需要在主进程文件中开启node:
odeIntegration: true,
contextIsolation: false
主进程代码如下:
// main.js
const { app, BrowserWindow } = require('electron')
app.on('ready', () => {
// 新建一个窗口
app.mainWindow = new BrowserWindow({
width: 800,
height: 600,
webPreferences: {
nodeIntegration: true, // 是否集成 Nodejs
contextIsolation: false,
},
})
// 加载渲染文件
app.mainWindow.loadFile('./index.html')
// 窗口关闭后清空变量
app.mainWindow.on('close', () => {
mainWindow = null
})
})
渲染进程代码如下:
// index.html
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta http-equiv="X-UA-Compatible" content="ie=edge" />
<title>读写文件测试</title>
</head>
<body>
<button onclick="readFile()">读取文件</button>
<button onclick="writeFile()">写入文件</button>
<p id="show_file_content">页面内容</p>
<script src="./testFile.js"></script>
</body>
</html>
新建一个testFile.js文件进行文件的读取和写入:
// 导入 node 的模块
const fs = require('fs')
const path = require('path')
const { log } = console
// 获取到文件展示的dom
const showContent = document.getElementById('show_file_content')
// 读取文件
function readFile() {
console.log('读取文件')
fs.readFile(path.join(__dirname, '/msg.txt'), (err, data) => {
if (err) {
throw new Error(err, '读取文件失败')
}
showContent.innerText = data
})
}
// 需要写入的内容
const content = '我今天学习了node.js'
// 写入文件
function writeFile() {
fs.writeFile(
path.join(__dirname, '/msg.txt'),
content,
'utf8',
(err, data) => {
if (err) {
return new Error(err, '读取文件失败')
}
log('写入文件成功')
}
)
}
新建测试文件msg.txt,内容为:“你今天学了什么”
最终效果如下:
进程间的通信
进程间的通信可以分为以下三种:
主进程 到 渲染进程:通过 webContents.send 来发送 --->ipcRenderer.on 来监听
渲染线程 到 主线程:通过 ipcRenderer.send发送 ---> ipcMain.on来监听
渲染进程 到 渲染进程:通过主进程转发或者通过ipcRenderer.sendTo指定渲染进程id进行发送
1. 主进程到渲染进程
webContents.send(channel, ...args)
channelString...argsany[]
主进程
mian.js
在主进程中使用 webContents.send 发送消息:
var { app, ipcMain, BrowserWindow } = require('electron');
const HTray = require('./tray').HTray
// 引入menu
require('./menu')
app.on('ready', () => {
app.win = new BrowserWindow({
width: 500,
height: 300,
webPreferences: {
nodeIntegration: true,
enableRemoteModule:true, // 启用remote
contextIsolation: false
}
})
// 发送给渲染线程
setTimeout(() => {
app.win.webContents.send('mainMsg', '我是主线程发送的消息')
}, 3000)
app.win.loadFile('index.html');
app.win.webContents.openDevTools();
// 监听关闭事件
app.win.on('close', (event) => {
// 1.隐藏窗口
app.win.hide();
// 2.隐藏任务栏
app.win.setSkipTaskbar(true);
// 3.阻止默认行为(因为并不是要关闭)
event.preventDefault();
})
})
app.on('window-all-closed', () => {
app.quit();
})
渲染进程 main.html 外链一个 render.js
在渲染线程中使用 ipcRenderer.on来进行监听
ipcRenderer.on(channel, listener)
channelStringlistenerFunction
// index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>electron_demo</title>
</head>
<style>
</style>
<body>
通信测试
<p id="receive">接收信息</p>
<script src="./render.js"></script>
</body>
</html>
// render.js
const electron = require('electron')
const { ipcRenderer } = require('electron')
const { log } = console
log(ipcRenderer)
ipcRenderer.on('mainMsg', (event, task) => {
log(task)
document.getElementById('receive').innerText = task
})
效果如下:
2. 渲染进程到主进程
在上一篇咱们写了一个托盘闪烁的功能,就是通过渲染进程给主进程发消息,主进程进行接收信号并处理的方法来实现的:
// index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>electron_demo</title>
</head>
<style>
</style>
<body>
<div>闪烁测试</div>
<button onclick="start()">开始闪烁</button>
<button onclick="stop()">停止闪烁</button>
<script>
const { ipcRenderer } = require('electron');
// 点击闪烁
function start() {
ipcRenderer.send("startFlash");
}
// 停止闪烁
function stop() {
ipcRenderer.send("stopFlash");
}
</script>
</body>
</html>
主进程:
// index.js
var { app, ipcMain, BrowserWindow } = require('electron');
const HTray = require('./tray').HTray
// 引入menu
require('./menu')
app.on('ready', () => {
app.win = new BrowserWindow({
width: 500,
height: 300,
webPreferences: {
nodeIntegration: true,
enableRemoteModule:true, // 启用remote
contextIsolation: false
}
})
// 创建系统托盘
app.tray = new HTray();
// 显示系统托盘
app.tray.show();
// 托盘闪烁
ipcMain.on('startFlash', (event, arg) => {
app.tray.startFlash();
})
// 停止闪烁
ipcMain.on('stopFlash', (event, arg) => {
app.tray.stopFlash();
})
app.win.loadFile('index.html');
app.win.webContents.openDevTools();
// 监听关闭事件
app.win.on('close', (event) => {
// 1.隐藏窗口
app.win.hide();
// 2.隐藏任务栏
app.win.setSkipTaskbar(true);
// 3.阻止默认行为(因为并不是要关闭)
event.preventDefault();
})
})
app.on('window-all-closed', () => {
app.quit();
})
3. 渲染进程到渲染进程
方法1:
ipcRenderer.sendTo(webContentsId, channel, ...args)
webContentsIdNumberchannelString...argsany[]
通过 ipcRenderer 发送消息到带有 webContentsId 的窗口.
前提是要知道对应的渲染进程的ID
方法2:
可以让主进程作为中转站,先从渲染进程发到主进程,在通过主进程转发到其他的渲染进程;
// 渲染进程A:
ipcRenderer.send('sendMsg', '哈哈哈哈哈');
// 主进程:
ipcMain.on('sendMsg', (event, arg) => {
win.webContents.send('sendMsgToRenderer2', arg)
})
// 渲染进程B:
ipcRenderer.on('sendMsgToRenderer2', (event, data) => {
console.log("渲染进程B接收到的数据", data)
})
以上例子就是electron中进程间的通信啦,更多使用方法可以查看官方文档哦!!!
官方文档:
感谢
谢谢你读完本篇文章,希望对你能有所帮助,如有问题欢迎各位指正。
我是Nicnic,如果觉得写得可以的话,请点个赞吧❤。
写作不易,「点赞」+「在看」+「转发」 谢谢支持❤
往期好文
《前端CSS高频面试题---1.CSS选择器、优先级、以及继承属性》