目前,您的preload.js
脚本仅配置为使用ipcRender.invoke()
,该ipcRender.invoke()
用于从渲染线程到主线程然后再返回到渲染线程。
如果你想从主线程到渲染线程,那么你需要使用contents.send(channel, ...args)
。
例如:mainWindow.webContents.send('channel', 'message');
.
要实现“关注点分离”并将硬编码函数排除在 preload.js
脚本之外,您可以重构您的 preload.js
脚本,使其仅反映您列入白名单的“通道”和相关的传输方法。这也大大提高了可读性。
请参阅下面的代码,了解对初始 IPC 调用函数调用、主线程实现以呈现线程 IPC 和新的 `preload.js 文件的更改。
index.html
(渲染线程)
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<meta http-equiv="Content-Security-Policy" content="default-src 'self'; script-src 'self'">
<title>IPC Example</title>
</head>
<body>
<h1>Wait on response...</h1>
<h2>0</h2>
</body>
<script src="./renderer.js"></script>
</html>
当您将<script>
标记放在html 文档的底部而不是<head>
标记中时,window.onload
的使用就变得多余了。
render.js
(渲染线程)
const counter = document.querySelector('h2');
// IIFE - Immediately Invoked Function Expression
(function() {
// Let's run the counter function.
counter();
// Listen on this channel for an incoming test.
window.ipcRender.receive('channel:test', (message) => {
console.log(message);
});
})();
//
function counter() {
setInterval(() => {
window.ipcRender.invoke('channel:count', counter.innerText)
.then((result) => {
counter.innerText = result;
})
}, 1000);
}
preload.js
(主线程)
const {contextBridge, ipcRenderer} = require('electron');
// White-listed channels.
const $ipc = {
'render': {
// From render to main.
'send': [],
// From main to render.
'receive': [
'channel:test'
],
// From render to main and back again.
'sendReceive': [
'channel:count'
]
}
};
// Exposed protected methods in the render process.
contextBridge.exposeInMainWorld(
// Allowed 'ipcRenderer' methods.
'ipcRender', {
// From render to main.
send: (channel, args) => {
let validChannels = $ipc.render.send;
if (validChannels.includes(channel)) {
ipcRenderer.send(channel, args);
}
},
// From main to render.
receive: (channel, listener) => {
let validChannels = $ipc.render.receive;
if (validChannels.includes(channel)) {
// Deliberately strip event as it includes `sender`.
ipcRenderer.on(channel, (event, ...args) => listener(...args));
}
},
// From render to main and back again.
invoke: (channel, args) => {
let validChannels = $ipc.render.sendReceive;
if (validChannels.includes(channel)) {
return ipcRenderer.invoke(channel, args);
}
}
}
);
app.js
(主线程)
const {app, BrowserWindow, ipcMain} = require('electron');
const path = require('path');
app.whenReady().then(() => {
const mainWindow = new BrowserWindow({
width: 500,
height: 500,
webPreferences: {
preload: path.join(__dirname, 'preload.js')
}
})
mainWindow.loadFile('index.html');
// Open the DevTools.
// mainWindow.webContents.openDevTools();
// ipc from render to main and back again.
ipcMain.handle('channel:count', (event, count) => {
return ++count;
})
// ipc from main to render.
mainWindow.webContents.send('channel:test', 'This is a test');
})
【讨论】:
-
感谢我使用
mainWindow.webContents.send('channel', 'message')
的答案 -
@Aaqu 如果这回答了您的问题,那么您可以通过单击答案顶部的赞成/反对票图标下方的灰色勾号图标来接受答案。如果它没有回答您的问题,请告诉我您需要哪些其他信息/帮助。
-
我没有足够的声望来添加向上箭头,抱歉
-
我在 preload.js 中添加了两个小改动,将 ipcRenderer 改为 ipcRenderer,并重命名了 counter 函数。现在工作正常