2 回答

TA貢獻1712條經驗 獲得超3個贊
require未定義,因為您沒有在nodeIntegration窗口上啟用。在您的窗口配置中將其設置為 true:
const window = new BrowserWindow({
transparent: true,
frame: false,
resizable: false,
center: true,
width: 410,
height: 550,
webPreferences: {
nodeIntegration: true
}
})

TA貢獻1829條經驗 獲得超6個贊
正如 AlekseyHoffman 所提到的,您無法ipcRenderer在前端 js 文件中訪問的原因是因為您已nodeIntegration設置為 false。也就是說,現在默認設置為 false 是有原因的。它使您的應用程序的安全性大大降低。
讓我建議一種替代方法:與其嘗試ipcRenderer通過設置為 true 來直接從前端 js訪問,不如nodeIntegration從 preload.js 訪問它。在 preload.js 中,您可以有選擇地公開您想要在前端訪問的 ipcMain 函數(來自您的 main.js 文件)(包括那些可以從 main.js 發回數據的函數),并通過ipcRenderer那里調用它們。在您的前端 js 中,您可以訪問公開這些功能的 preload.js 對象;preload.js 然后將調用這些 main.js 函數ipcRenderer,并將數據返回給調用它的前端 js。
這是一個簡單但完全有效的示例(這些文件應該足以構建一個在 main.js 和前端之間具有雙向通信的電子應用程序。在此示例中,以下所有文件都位于同一目錄中。):
main.js
// boilerplate code for electron..
const {
app,
BrowserWindow,
ipcMain,
contextBridge
} = require("electron");
const path = require("path");
let win;
/**
* make the electron window, and make preload.js accessible to the js
* running inside it (this will allow you to communicate with main.js
* from the frontend).
*/
async function createWindow() {
// Create the browser window.
win = new BrowserWindow({
width: 800,
height: 600,
webPreferences: {
nodeIntegration: false, // is default value after Electron v5
contextIsolation: true, // protect against prototype pollution
enableRemoteModule: false,
preload: path.join(__dirname, "./preload.js") // path to your preload.js file
}
});
// Load app
win.loadFile(path.join(__dirname, "index.html"));
}
app.on("ready", createWindow);
// end boilerplate code... now on to your stuff
/**
* FUNCTION YOU WANT ACCESS TO ON THE FRONTEND
*/
ipcMain.handle('myfunc', async (event, arg) => {
return new Promise(function(resolve, reject) {
// do stuff
if (true) {
resolve("this worked!");
} else {
reject("this didn't work!");
}
});
});
請注意,我使用的示例是ipcMain.handle因為它允許雙向通信并返回一個 Promise 對象 - 即,當您通過 preload.js 從前端訪問此函數時,您可以使用其中的數據取回該 Promise。
preload.js:
// boilerplate code for electron...
const {
contextBridge,
ipcRenderer
} = require("electron");
// All of the Node.js APIs are available in the preload process.
// It has the same sandbox as a Chrome extension.
window.addEventListener('DOMContentLoaded', () => {
const replaceText = (selector, text) => {
const element = document.getElementById(selector)
if (element) element.innerText = text
}
for (const type of ['chrome', 'node', 'electron']) {
replaceText(`${type}-version`, process.versions[type])
}
})
// end boilerplate code, on to your stuff..
/**
* HERE YOU WILL EXPOSE YOUR 'myfunc' FROM main.js
* TO THE FRONTEND.
* (remember in main.js, you're putting preload.js
* in the electron window? your frontend js will be able
* to access this stuff as a result.
*/
contextBridge.exposeInMainWorld(
"api", {
invoke: (channel, data) => {
let validChannels = ["myfunc"]; // list of ipcMain.handle channels you want access in frontend to
if (validChannels.includes(channel)) {
// ipcRenderer.invoke accesses ipcMain.handle channels like 'myfunc'
// make sure to include this return statement or you won't get your Promise back
return ipcRenderer.invoke(channel, data);
}
},
}
);
渲染器進程(即您的前端 js 文件 - 我將其稱為 frontend.js):
// call your main.js function here
console.log("I'm going to call main.js's 'myfunc'");
window.api.invoke('myfunc', [1,2,3])
.then(function(res) {
console.log(res); // will print "This worked!" to the browser console
})
.catch(function(err) {
console.error(err); // will print "This didn't work!" to the browser console.
});
索引.html
<!DOCTYPE html>
<html>
<head>
<title>My Electron App</title>
</head>
<body>
<h1>Hello Beautiful World</h1>
<script src="frontend.js"></script> <!-- load your frontend script -->
</body>
</html>
包.json
{
"name": "myapp",
"main": "main.js",
"scripts": {
"start": "electron ."
}
}
上面的文件應該足以擁有一個在 main.js 和前端 js 之間進行通信的完整工作的電子應用程序。將它們全部放在一個名為main.js、preload.js、frontend.js和的目錄中index.html,然后package.json使用npm start. 請注意,在此示例中,我將所有文件存儲在同一目錄中;確保將這些路徑更改為它們存儲在系統上的任何位置。
添加回答
舉報