问题描述
我在 Electron JS 中有一个应用程序,它调用 python 函数来执行 python 脚本.当脚本执行时,它应该将数据发送回 Electron JS GUI 并显示它.
I have an application in Electron JS that is calling a python function to execute a python script. When the script executes it should send the data back to the Electron JS GUI and display it.
我遇到的问题是它说 join 是未定义的:
The issue I am having is that it is saying that join is undefined:
weather.js:9 Uncaught TypeError: Cannot read property 'join' of不明确的在 get_weather (weather.js:9)在 HTMLButtonElement.onclick (weather.html:14)
weather.js:9 Uncaught TypeError: Cannot read property 'join' of undefined at get_weather (weather.js:9) at HTMLButtonElement.onclick (weather.html:14)
这是我的 JavaScript 文件:
here is my JavaScript file:
let {PythonShell} = require('python-shell')
var path = require("path")
function get_weather() {
var city = document.getElementById("city").value
var options = {
scriptPath : path.join(__dirname, '/../engine/'),
args : [city]
}
let pyshell = new PythonShell('weatherApp.py', options);
pyshell.on('message', function(message) {
swal(message);
})
document.getElementById("city").value = "";
}
scriptPath : path.join(__dirname, '/../engine/')"这一行似乎是有问题的代码.
The line "scriptPath : path.join(__dirname, '/../engine/')," seems to be the offending piece of code.
我的gui.html文件如下:
My gui.html file is as follows:
<html>
<head>
<title></title>
<meta charset="UTF-8">
</head>
<body>
<h1>Get your local weather ...</h1>
<br>
<br>
<label>Enter city name here: <label>
<input id="city" type = "text" placeholder="City">
<button type = "button" value="clickme" onclick="get_weather()">Get Weather</button>
<!--- <button class="btn btn-success" onclick="get_weather();">Go!</button> -->
<br>
<br>
<br>
<script src="/home/ironmantis7x/Documents/BSSLLC/projects/node_electron/electronDemoApps/guiApp/gui/linkers/weather.js"></script>
<p><button type="button"><a href="gui.html">Back to Main Page</a></button>
</body>
</html>
我需要修复哪些错误才能使其正常工作?
What error(s) do I need to fix to get this working correctly?
谢谢.
推荐答案
问题
自 Electron 5 起 nodeIntegration
默认在窗口中被禁用.由于普通浏览器 API 不知道 require
或 join
,因此在尝试时会出错.
Since Electron 5 nodeIntegration
is disabled by default in the window. Since normal browser API does not know require
or join
, you get errors when you try.
重新启用节点集成
您可以再次启用 nodeIntegration
,但由于某种原因它被禁用了.请务必阅读并理解 电子安全教程.
You could enable nodeIntegration
again, but it was disabled for a reason. Be sure you read and understand the electron security tutorial.
使用预加载脚本
另一种方法是使用预加载脚本.让我们看一下 BrowserWindow
文档.
Another way is to use a preload script. Let's have a look at the BrowserWindow
documentation.
创建新的 BrowserWindow 时,您可以添加多个选项.对于这种情况,我们需要 webPreferences.preload
选项:
When creating a new BrowserWindow you can add several options. For this case we need the webPreferences.preload
option:
指定将在页面中运行其他脚本之前加载的脚本.无论节点集成是打开还是关闭,此脚本都将始终可以访问节点 API.该值应该是脚本的绝对文件路径.关闭节点集成后,预加载脚本可以将 Node 全局符号重新引入全局范围.
Specifies a script that will be loaded before other scripts run in the page. This script will always have access to node APIs no matter whether node integration is turned on or off. The value should be the absolute file path to the script. When node integration is turned off, the preload script can reintroduce Node global symbols back to the global scope.
请注意,预加载脚本是在渲染器进程中运行的.
Be aware that the preload script is run in the renderer process.
示例
以下是一个示例应用程序,它打开一个带有按钮的窗口,该按钮使用电子 dialog
来选择文件.这不适用于禁用的 nodeIntegration
,但由于我们的预加载脚本,我们将 dialog.showOpenDialog()
重新引入了我们的窗口.
Following is an example app, that opens a window with a button that uses the electron dialog
to select files. This would not work with disabled nodeIntegration
but thanks to our preload script, we reintroduced dialog.showOpenDialog()
to our window.
main.js
const { app, BrowserWindow } = require("electron");
const { join } = require("path");
let win;
app.on("ready", () => {
win = new BrowserWindow({
webPreferences: {
//this is the default since electron 5
nodeIntegration: false,
//here you load your preload script
preload: join(__dirname, "preload.js")
}
});
win.loadURL(join(__dirname, "index.html"));
});
preload.js
const { dialog } = require("electron").remote;
window.mystuff = {
selectFile
};
async function selectFile() {
const files = await dialog.showOpenDialog({
properties: ["openFile", "multiSelections"]
});
return files;
}
index.html
<html>
<body>
<main>
<button onclick="myFunction()">select file</button>
<ul id="foo"></ul>
</main>
<script>
async function myFunction() {
//the function provided by the preload script
const files = await window.mystuff.selectFile();
const list = document.getElementById("foo");
for (const file of files) {
const node = document.createElement("LI");
const textNode = document.createTextNode(file);
node.appendChild(textNode);
list.appendChild(node);
}
}
</script>
</body>
</html>
通过 IPC 发送事件
如果您不确定您的功能是否应该在窗口中显示,您也可以通过 ipcRenderer
发送事件.
If you are unsure your functionality should be exposed in the window, you can also send events via ipcRenderer
.
preload.js
const { ipcRenderer } = require("electron");
window.mystuff = {
selectFile
};
function selectFile() {
return new Promise(resolve => {
ipcRenderer.on("selected-files", (e, files) => {
resolve(files);
});
ipcRenderer.send("select-files");
});
}
main.js中的附加部分
ipcMain.on("select-files", async () => {
const files = await dialog.showOpenDialog({
properties: ["openFile", "multiSelections"]
});
win.webContents.send("selected-files", files);
});
这篇关于无法读取 Javascript 文件 Electron JS 中未定义的属性“加入"的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持编程学习网!