Electron窗口数据传输报错求助:Web转GUI应用遇问题
问题描述
我正在将Web项目转为基于Electron的GUI应用,参考某视频教程启动项目,原教程使用Yarn,我用的是npm 9.2.0。最初点击按钮毫无响应,根据评论修改webPreferences配置后出现报错。
修改前后的配置对比
修改前的webPreferences配置
webPreferences:{ nodeIntegration: true, }
修改后的webPreferences配置(修改后触发报错)
webPreferences:{ nodeIntegration: true, contextIsolation: false, enableRemoteModule: true, }
当前代码
gui.js
const { app, BrowserWindow, ipcMain } = require("electron"); let leftWindow = null; let rightWindow = null; const createWindows = (win, page) => { win = new BrowserWindow({ width: 1024, height: 600, resizable: false, fullscreen: true, webPreferences:{ nodeIntegration: true, contextIsolation: false, enableRemoteModule: true, }, }); win.loadFile(page) }; app.whenReady().then(() => { //createWindows(leftWindow, "dash.html"); createWindows(rightWindow, "controls.html"); }); app.on('window-all-closed', () => { if(process.platform !== 'darwin') { app.quit() } }) ipcMain.on('send', (event, data) => { const randomStr = data + Math.random().toString(36).substring(2, 5) rightWindow.webContents.send('receive', randomStr) })
render.js
const ipcRenderer = require("electron").ipcRenderer; const test = () => { ipcRenderer.send("send", document.querySelector(".keyWord").value); }; ipcRenderer.on("receive", (event, data) => { alert(data); const tempTag = document.querySelector("#temp"); tempTag.innerText = data; });
controls.html
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Controls</title> <script defer src="render.js"></script> <link rel="stylesheet" href="./public/styles.css" /> </head> <body> <div id="content"> <input type="text" class="keyWord" placeholder="Enter Data"> <button onclick="test()">Test</button> <h1 id="temp">Random String</h1> </div> <script type="text/jsx" src="./public/controlApp.jsx"></script> </body> </html>
解决方案
1. 修复窗口实例赋值问题
createWindows函数里的win是局部变量,赋值后不会修改外部的rightWindow变量,导致ipcMain.on('send')里的rightWindow始终为null,触发报错。修改函数让它返回窗口实例:
const createWindows = (page) => { const win = new BrowserWindow({ width: 1024, height: 600, resizable: false, fullscreen: true, webPreferences:{ nodeIntegration: true, contextIsolation: false, }, }); win.loadFile(page); return win; }; // 调用时直接赋值给变量 app.whenReady().then(() => { // leftWindow = createWindows("dash.html"); rightWindow = createWindows("controls.html"); });
2. 移除废弃配置项
enableRemoteModule在Electron 14及以上版本已被废弃,不需要配置该选项,直接移除即可。
3. 确保test函数全局可访问
按钮的onclick="test()"依赖全局作用域的test函数,把函数挂载到window对象上:
// render.js const ipcRenderer = require("electron").ipcRenderer; window.test = () => { ipcRenderer.send("send", document.querySelector(".keyWord").value); }; ipcRenderer.on("receive", (event, data) => { alert(data); const tempTag = document.querySelector("#temp"); tempTag.innerText = data; });
4. 可选:使用Electron安全最佳配置(推荐)
如果想遵循安全规范,不要关闭contextIsolation,改用预加载脚本暴露API:
- 创建
preload.js:
const { contextBridge, ipcRenderer } = require('electron'); contextBridge.exposeInMainWorld('electronAPI', { sendData: (data) => ipcRenderer.send('send', data), onReceiveData: (callback) => ipcRenderer.on('receive', callback) });
- 修改
webPreferences:
const path = require('path'); // ... webPreferences:{ contextIsolation: true, nodeIntegration: false, preload: path.join(__dirname, 'preload.js') }
- 修改
render.js:
window.test = () => { window.electronAPI.sendData(document.querySelector(".keyWord").value); }; window.electronAPI.onReceiveData((event, data) => { alert(data); const tempTag = document.querySelector("#temp"); tempTag.innerText = data; });
内容的提问来源于stack exchange,提问作者Grez
相关产品推荐
相关产品推荐

