与nodejs进行通信
默认情况下,客户端的代码,是没法直接使用nodejs的api的,那么如果我们要使用这方面的能力应该怎么做呢?
第一种方法 进程间进行通信官方教程
大概的思路就是,使用preload.js
,挂载一个公用的api比如这样
依赖的apiipcRenderer.send
和 ipcMain.on
js
// preload.js
const { contextBridge, ipcRenderer } = require("electron");
contextBridge.exposeInMainWorld("electronAPI", {
setTitle: (title) => ipcRenderer.send("setTitle", title),
});
1
2
3
4
5
2
3
4
5
在main.js
中进行接收,这是一个订阅者模式
js
const { app, BrowserWindow, ipcMain } = require("electron");
const path = require("path");
const createWindow = () => {
const win = new BrowserWindow({
width: 800,
height: 600,
webPreferences: {
preload: path.join(__dirname, "preload.js"),
},
});
ipcMain.handle("ping", () => "ping");
ipcMain.on("setTitle", (event, title) => {
const webContents = event.sender;
const win = BrowserWindow.fromWebContents(webContents);
win.setTitle(title);
});
win.loadFile("index.html");
};
app.whenReady().then((res) => {
createWindow();
app.on("window-all-closed", () => {
if (process.platform !== "darwin") app.quit();
});
app.on("activate", () => {
if (BrowserWindow.getAllWindows().length === 0) createWindow();
});
});
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
在render.js
中调用preload.js
中暴露出来的api,从而实现交互:
js
// render.js
const button = document.querySelector("button");
const input = document.querySelector("#input");
const ping = async () => {
const value = input.value
electronAPI.setTitle(value)
};
button.addEventListener("click", ping);
1
2
3
4
5
6
7
8
9
2
3
4
5
6
7
8
9
第二种方法,就是上面提到的方法【如何与nodejs进程同行通信】
这种方法依赖的api是 ipcRenderer.invoke
和 ipcMain.handle
第三种方案 主渲染器(Main to renderer)
主要依赖的是ipcRenderer.on
,假如node层希望去通知客户端层,可以使用下面这种方法
- 在
preload.js
暴露出一个钩子,可以让客户端监听到
javascript
const { contextBridge, ipcRenderer } = require("electron");
contextBridge.exposeInMainWorld("electronAPI", {
onUpdateCounter: (callback) => ipcRenderer.on('update-counter', callback)
});
1
2
3
4
5
2
3
4
5
WARNING
这里出于安全性的考虑,并没有将整个的ipcRenderer.on
函数暴露了,而只是暴露出来一个key
- 在
render.js
中进行监听
javascript
window.electronAPI.onUpdateCounter((_event, value) => {
const oldValue = Number(counter.innerText)
const newValue = oldValue + value
counter.innerText = newValue
// 在这里我们可以使用event的这个参数,直接再次和node层进行交互
_event.sender.send('counter-value', newValue)
})
1
2
3
4
5
6
7
8
2
3
4
5
6
7
8
- 在
main.js
中发送事件
这里模拟一个node希望和客户端交互的场景,我们创建出来两个菜单,并且发送事件,在win.webContents.send('update-counter', value)
发送的事件,会被客户端的回调函数中接收到,从而产生交互
javascript
const { app, BrowserWindow, ipcMain, dialog, Menu } = require("electron");
const path = require("path");
const createWindow = () => {
const win = new BrowserWindow({
width: 800,
height: 600,
webPreferences: {
preload: path.join(__dirname, "./src/preload.js"),
},
});
const menu = Menu.buildFromTemplate([
{
label: app.name,
submenu: [
{
click: () => win.webContents.send('update-counter', 1),
label: 'count+1',
},
{
click: () => win.webContents.send('update-counter', -1),
label: 'count-1',
}
]
}
])
Menu.setApplicationMenu(menu)
win.loadFile("./index.html");
win.webContents.openDevTools()
};
app.whenReady().then((res) => {
ipcMain.on('counter-value', (_event, value) => {
console.log(value) // 在这里监听,获得客户端返回的参数
})
createWindow();
app.on("window-all-closed", () => {
if (process.platform !== "darwin") app.quit();
});
app.on("activate", () => {
if (BrowserWindow.getAllWindows().length === 0) createWindow();
});
});
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49