每个页面程序通过渲染和主进程通信,主进程根据需求调用Native Api来实现功能。
实际,每个页面和主程序通信时,需要建个桥梁来管理它们的通信,preload.js(自己创建),来管理实现通信。
----创建preload.js定义桥梁js:
----关于主程序与渲染层的通信:
写入/传入:send->on 读取:invoke->handle (预加载脚本 / 桥梁->主进程)
详细解析:
send
和on
的关系(主进程 <---> 渲染进程): 简易通信,不需要返回值send
是发送消息的动作。on
是接收消息的动作。- 渲染进程通过
ipcRenderer.send
发送消息,主进程通过ipcMain.on
接收消息。反之,主进程也可以通过event.sender.send
向渲染进程发送消息,渲染进程通过ipcRenderer.on
接收。
invoke
和handle
的关系(渲染进程 ---> 主进程): 处理异步操作,有返回值invoke
是发送请求并期望响应的动作。handle
是处理请求并返回响应的动作。- 渲染进程通过
ipcRenderer.invoke
发送请求,主进程通过ipcMain.handle
处理请求并返回结果
总结:
send
/on
:适用于简单的事件驱动通信,不需要返回值。invoke
/handle
:适用于需要返回值或处理异步操作的场景,更加现代化和灵活
main.js(主程序)里的代码:
const {app, BrowserWindow,ipcMain} = require('electron')
const path = require('path')
const fs = require('fs')
//写入文件
function writeFile(_, data) {
fs.writeFileSync('D:/hello.txt', data)
}
//读取文件
function readFile() {
const res = fs.readFileSync("D:/hello.txt").toString()
return res
}
function createWindow() {
//当app准备好后,执行createWindow创建窗口
const win = new BrowserWindow({
width: 800,//窗口宽度
height: 600,//窗口高度
autoHideMenuBar: true,//自动隐藏菜单档
alwaysOnTop: true,//置顶
webPreferences: { //在main.js中定义preload.js为桥梁
preload: path.resolve(__dirname, './preload.js')
}
})
ipcMain.on('file-save', writeFile)
ipcMain.handle('file-read', readFile)
//引入页面
win.loadFile('./pages/index/index.html')
win.openDevTools() //自动打开调试窗口
console.log("main.js里的main.js")
}
app.on('ready', () => {
createWindow()
//兼容核心代码1
app.on('activate', () => {
if (BrowserWindow.getAllWindows().length === 0) createWindow()
})
})
preload.js(桥梁)里的代码 :
const {contextBridge, ipcRenderer} = require('electron')
contextBridge.exposeInMainWorld('myAPI', {
version: process.version,
saveFile: (data) => {
ipcRenderer.send('file-save', data)
},
readFile() {
//返回的是一个primise的返回值
return ipcRenderer.invoke('file-read')
}
})
render.js(渲染)里的代码:
const btn1 = document.getElementById("btn1")
const btn2 = document.getElementById("btn2")
const btn3 = document.getElementById("btn3")
const input = document.getElementById("inp")
btn1.onclick = () => {
alert(myAPI.version)
}
btn2.onclick = () => {
myAPI.saveFile(input.value)
}
btn3.onclick = async() => {
const res = await myAPI.readFile()
alert(res)
}
html的代码:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="Content-Security-Policy" content="default-src 'self'; script-src 'self'">
<title>这里是index页面</title>
</head>
<body>
<h1>欢迎学习Electron开发!!!</h1>
<button id="btn1">点我</button>
<hr/>
<input type="text" id="inp"/>
<button id="btn2">向D盘写入hello.txt</button>
<hr>
<button id="btn3">读取hello.txt的内容</button>
</body>
<script type="text/javascript" src="./render.js"></script>
</html>