【问题标题】:electron js - cannot get button to perform simple actions from click电子js - 无法通过点击获得按钮来执行简单的操作
【发布时间】:2021-11-23 08:37:22
【问题描述】:

长话短说,我正在开发一个通过本地网络发送命令的单页应用程序。测试 Electron JS,我什至无法获得一个简单的按钮来工作。我觉得我并没有以某种方式将 main.js 和 index.js 之间的逻辑联系起来,但对于我的一生,我无法找出正确的方法来做到这一点。我什至在 index.js 和 main.js 和 index.html 中设置了断点,但是除了 main.js 中的断点之外,没有一个断点被击中。我在 preload.js 文件中放置了一个简单的函数,并且该函数被正确调用,但我试图附加到位于 index.html 和 index.js 中的按钮的那个函数甚至从未被点击。很多被注释掉的代码是我想记住的东西,或者是我注意到一种不同的创建方法,只是想试试看是否有效。如果有人有任何答案或指导,将不胜感激! :D

下面是我的 main.js

//#region ---for dev only | hot reload
try {
    require('electron-reloader')(module)
} catch (_) {}
//#endregion
const electron = require('electron');
const {app, BrowserWindow, Menu} = require('electron');
const path = require('path');
const ipcMain = electron.ipcMain;

//#region globals
const SRC_DIR = '/src/'
const IMG_DIR = '/assets/images'
//#endregion

function createWindow () { 
    const win = new BrowserWindow({
        width: 800,
        height: 600,                
        //frame: false,
        webPreferences: {  
            contextIsolation: true,          
            preload: path.join(__dirname, 'preload.js')
        }
    });

    //Used to auto open dev tools for debugging
    //win.openDevTools();    
    
    win.loadFile('src/index.html');
    // win.loadURL(url.format({
    //     pathname: path.join(__dirname, 'index.html'),
    //     protocol: 'file',
    //     slashes: true
    // }));
}

app.whenReady().then(() => {    
    //nativeTheme.shouldUseDarkColors = true;
    createWindow();
})

//closes app processes when window is closed 
app.on('window-all-closed', function () {
    if (process.platform !== 'darwin') app.quit();
})

var menu = Menu.buildFromTemplate([
    {
        label: 'Menu',
        submenu: [
            {label: 'Edit'},
            {type: 'separator'},
            {
                label: 'Exit',
                click() {
                    app.quit();
                }
            }
        ]
    }
])

Menu.setApplicationMenu(menu);

这里是 index.html

<!DOCTYPE html>
<html>
  <head>
    <meta charset="UTF-8">    
    <meta http-equiv="Content-Security-Policy" content="default-src 'self'; script-src 'self'">
    <meta http-equiv="X-Content-Security-Policy" content="default-src 'self'; script-src 'self'">
    <title>Ecas Software</title>
    <link rel="stylesheet" href="index.css">
  </head>
  <body>
    <p id="myText">Let's get started :)</p>    
    <button id="myBtn">Change Text</button>
    <script type="text/javascript" src="./index.js" ></script>    
  </body>
</html>  

最后是我的 index.js(也就是我的第一个也是唯一一个渲染器?)

const electron = require('electron');

const chgBtn = document.getElementById('myBtn');

function replaceText(selector, text){
    const element = document.getElementById(selector);
    if (element) element.innerText = text;
}    

chgBtn.onclick = function() {
    replaceText('myText', 'no boom...');
}

// chgBtn.addEventListener('click', function(){
//     // if (document.getElementById('myText').innerText == 'boom'){
//     //     replaceText('myText','no boom...');    
//     // } else {
//     //     replaceText('myText','boom');    
//     // }    
//     document.alert("working function");
// });


//chgBtn.addEventListener('click', replaceText('myText','no boom...'));

【问题讨论】:

  • 尝试在浏览器窗口中将contextIsolation设置为false,然后将nodeIntegration设置为true

标签: javascript html node.js electron


【解决方案1】:

为什么会出现这个错误

这里的问题是您没有按照 Electron 的预期使用脚本文件。

如果您使用 Devtools 控制台(通过取消注释 win.openDevTools()),您应该会在控制台中看到此错误:

Uncaught ReferenceError: require is not defined (from index.js file)

这是因为您的 index.js 文件作为“普通 javascript 文件”加载。如果您想使用 Node 语法(也称为“require”语法),您需要在 preload 脚本 中进行。只有 preload 脚本可以使用 require 语法,因为它是 Electron 允许使用 Node 的唯一脚本。

您也可以使用其他 javascripts 文件,方法是将其导入您的 HTML,就像您对 index.js 文件所做的那样,但您应该删除 require 调用。 由于“require”调用(在第一行)会抛出错误,因此以下所有代码都不会运行。这就是您的按钮在点击时没有反应的原因。

正确的做法

如果您需要使用 Electron Renderer API 中的某些方法(例如 ipcRenderer),您需要将其放入预加载脚本中。

如果你想使用自己的脚本,在一个单独的文件中,你也可以这样做,你将无法直接调用 Electron API。如果您想在自己的脚本中调用 Electron API,有一个解决方案,它被称为Context Bridge。这允许您在预加载脚本中创建一个可以使用 Electron API 的对象。您可以为此对象命名,然后使用 window 全局对象从您的其他脚本中调用它。

例如,如果你想使用ipcRenderer.send(channel, payload)

// Preload script
const { contextBridge, ipcRenderer } = require('electron')

contextBridge.exposeInMainWorld('theNameYouWant',
    {
        send: (channel, payload) => ipcRenderer.send(channel, payload)
    }
)

// index.js file, imported in your HTML file

window.theNameYouWant.send("channel-name", { someData: "Hello" })

在你的例子中

// Add this in your main.js file to see when a user click on the button from main process
ipcMain.on("button-clicked", (event, data) => console.log(data))
// Preload script
const { contextBridge, ipcRenderer } = require("electron")

contextBridge.exposeInMainWorld("electron", {
    send: (channel, payload) => ipcRenderer.send(channel, payload),
})
// index.js
const chgBtn = document.getElementById("myBtn")

function replaceText(selector, text) {
    const element = document.getElementById(selector)
    if (element) element.innerText = text
}

chgBtn.onclick = function () {
    replaceText("myText", "no boom...")
    window.electron.send("button-clicked", { someData: "Hello" })
}

【讨论】:

  • 非常感谢!这种上下文/数据流没有点击,我最近对 ​​JS 的接触变得一团糟;大量信息超载和不同日期的教程!你的答案是完美的@Dony,我现在理解我的错误以及如何继续前进。再次感谢! :)
猜你喜欢
  • 2022-12-02
  • 2023-03-22
  • 1970-01-01
  • 2020-11-04
  • 1970-01-01
  • 2020-08-21
  • 2014-03-31
  • 1970-01-01
  • 2022-01-03
相关资源
最近更新 更多