electron主进程和渲染进程通信
一、渲染进程文件(以vue文件为例)
首先定义了三个按钮
<el-button style="margin-left: 10px" @click="testFile">扫描文件</el-button>
<el-input placeholder="文件路径" style="width: 250px;margin-left: 5px" v-model="filePath"/>
<el-button style="margin-left: 10px" @click="testMkdir">创建目录</el-button>
<el-button style="margin-left: 10px" @click="testCopyFile">拷贝文件</el-button>
按钮对应点击事件触发的方法,通过引入electron的ipcRenderer向主进程发送消息。
1.(渲染进程向主进程发消息)ipcRenderer.send(channel,args):通过 channel 向主进程发送异步消息,args可传入任意参数
2.(渲染进程接收主进程消息)ipcRenderer.on(channel, listener):监听 channel, 当有新消息到达,使用 listener(event, args…) 调用 listener .
<script>
import {mapState} from 'vuex'
const {ipcRenderer} = window.require('electron');
export default {
name: 'fileManage',
data() {
return {}
},
created() {
},
mounted() {
},
methods: {
testFile() {
ipcRenderer.send('scanningFiles', this.filePath)
ipcRenderer.on('read-file', (event, args) => {
console.log(args.filePath)
})
},
testMkdir(){
ipcRenderer.send('testMkdir',this.filePath)
},
testCopyFile(){
ipcRenderer.send('testCopyFile',{
sourceFile:'D:\\xxx.txt',
destFile:'C:\\Users\\sheng_xin\\Desktop\\testMkdir\\test1\\test2\\xxx.txt'
})
},
}
}
</script>
二、主进程electron.js文件
主进程通过ipcMain.on监听并响应渲染进程对应通道发送过来的消息
1.(主进程接收渲染进程消息)ipcMain.on(channel, listener):监听 channel, 当新消息到达,将通过 listener(event, args…) 调用 listener.
2.(主进程响应渲染进程回复消息):event.sender.send(channel,args)
const {app, BrowserWindow, dialog, ipcMain} = require('electron');
const path = require("path");
const electron = require('electron');
const fs = require('fs');
/*获取electron窗体的菜单栏*/
const Menu = electron.Menu;
/*隐藏electron创建的菜单栏*/
Menu.setApplicationMenu(null);
let mainWindow;
let fileList;
function createWindow() { //创建一个新窗口
mainWindow = new BrowserWindow({
show: false,
webPreferences: {
nodeIntegration: true, // 是否集成 Nodejs
},
});
mainWindow.maximize(); //窗口最大化
// 打开开发者工
mainWindow.webContents.openDevTools();
mainWindow.on('closed', function () { //窗口关闭方法
mainWindow = null
});
// mainWindow.loadURL(`file://${__dirname}/index.html`); //窗口主文件地址
mainWindow.loadURL(`http://localhost:8001/`); //项目启动地址
}
ipcMain.on('scanningFiles', function (event, args) {
dive(args);
/*扫描目录获取文件*/
function dive(dir) {
fs.readdir(dir, function (err, list) {
list.forEach(function (file) {
let path = dir + "\\" + file;
let state = fs.lstatSync(path);
if (state.isDirectory()) {
console.log(path + '是文件夹');
//递归
dive(path);
} else {
fs.readFile(path, (err, data) => {
if (err) throw err;
event.sender.send('read-file', {filePath: path, data: data})
});
console.log(path + '是文件');
}
});
});
}
});
/*测试递归新建文件夹*/
ipcMain.on('testMkdir', function (event, args) {
console.log(args);
fs.mkdir(args, {recursive: true}, (err) => {
if (err) throw err;
});
});
ipcMain.on('testCopyFile', function (event, args) {
// console.log(args)
console.time('copying');
fs.stat(args.sourceFile, (err, stat) => {
// console.log(stat)
const fileSize = stat.size;
let bytesCopied = 0;
const readStream = fs.createReadStream(args.sourceFile);
readStream.on('data', (buffer) => {
bytesCopied += buffer.length;
const porcentage = ((bytesCopied / fileSize) * 100).toFixed(3);
console.log(porcentage + '%');
});
readStream.on('end', () => {
// console.log('end')
console.timeEnd('copying');
});
readStream.pipe(fs.createWriteStream(args.destFile));
});
});
/*删除目录*/
/*function deleteAll(path) {
let files = [];
if (fs.existsSync(path)) {
files = fs.readdirSync(path);
files.forEach(function (file, index) {
let curPath = path + "\\" + file;
if (fs.statSync(curPath).isDirectory()) {
deleteAll(curPath);
} else {
fs.unlinkSync(curPath);
}
});
fs.rmdirSync(path);
}
}*/
//以下就是类似于app的生命周期的方法
app.on('ready', () => {
createWindow();
});
app.on('window-all-closed', () => {
if (process.platform !== 'darwin') {
app.quit();
}
});
app.on('activate', () => {
if (mainWindow === null) {
createWindow();
}
});
渲染进程与主进程完成通信之后,我在渲染进程点击‘拷贝文件’,即可发送消息到主进程,利用主进程写操作文件的逻辑,完成文件的拷贝。我这里还打印了文件拷贝时间进度和时间(1.5G的文件)。
总结
本篇只介绍了简单的使用electron开发是主进程和渲染进程的通信方法,主要的流程其实很简单,通信方式的API可参考详细的Electron官方文档 https://www.electronjs.org/docs.。