【问题标题】:How to modify the HTML file used in an Electron's BrowserWindow?如何修改电子浏览器窗口中使用的 HTML 文件?
【发布时间】:2020-06-30 23:54:11
【问题描述】:

我正在尝试根据主流程中当前显示的内容弹出一个带有自定义“表单”的对话框。 例如:如果我在主窗口上显示了一个名为“锻炼”的表格,那么当按下按钮时,我想显示一个模式窗口,该窗口具有与所述锻炼相对应的输入字段,当用户输入任何内容时想要输入,然后我希望他们能够按 Enter 和/或有一个按钮来关闭所述模式窗口,然后将信息发送到主进程或渲染进程。

我想这样做的方法是创建一个空的 BrowserWindow 来表示对话框,然后它会检查当前显示的表格是什么。如果表格是“锻炼”,则在浏览器窗口中注入一些 HTML,以便有 3 个具有特定最小值、最大值等的输入字段。

我试过这样做(不检查当前表,只是想看看我是否可以注入 HTML)

let child = new BrowserWindow({modal: true, width: 400, height: 300, show: false});

child.loadURL(url.format({
    pathname: path.join(__dirname, 'modal.html'),
    protocol: 'file', 
    slashes: true
}))

child.document.getElementById('textHere').innerHTML += `<input ...>`;

child.once('ready-to-show', () => { 
    child.show();
})

child.setTitle(currTable);

但它似乎没有添加任何东西,事实上,当我尝试这样做时,我收到一条错误消息,提示“无法读取未定义的“getElementById””。

我想,这可能是因为我尝试在运行 child.show() 之前添加元素,所以我尝试将 ... += &lt;input ...&gt; 放在 child.show() 之后,但我遇到了同样的问题。

编辑;解决方案:问题是我不了解 IPC 通信,我仍然在为实现而苦苦挣扎,但在这里它如何为其他苦苦挣扎的人工作。

你有 main.js,它创建你的第一个 BrowserWindow,这个 BrowserWindow 加载一个名为 foo.html [可以用 .loadURL 完成]的 HTML 文件,它里面有这个:

&lt;script&gt;require('./foo.js');&lt;/script&gt;

这意味着 foo.js 正式是负责 foo.html 的 Renderering 进程,因此,如果要操作 foo.html,则必须通过 foo.js。

现在是场景,我在 foo.html 上有一个按钮。该按钮在 foo.js 中有一个 onClick 事件处理程序。如果我想在单击按钮时在屏幕上弹出一个新窗口[记住主进程,在这种情况下,main.js(因为它是创建第一个 BrowserWindow 的那个)负责所有 BrowserWindow management],然后我想,onClick,向 main.js 发送一个信号,告诉它创建一个新的 BrowserWindow,我会在 foo.js 的按钮处理程序中这样做:

ipcRender.send('message', data);

现在,如果你在主进程中添加一个相应的“接收器”,主进程就可以接收信号了:

ipcMain.on('message', function(event, arg){
//Do What you want based on the args, for instance one could specify that it's a dialog box
//Data is one of the args(Not 10000% sure of this but think so)
}

创建 BrowserWindow 并加载 URL 后,您可以通过执行 windowName.webContents.send('message', data); 将消息发送回 Renderer 进程。现在您必须接收从主进程发送的此消息,要接收它,请执行ipcRender.on('message', function(){} //); //This function could already be predefined, like loadXDialog, loadYDialog, etc.

你就完成了!

注意:如果我做错了什么,请不要犹豫,纠正我,我从 Reddit 上的某个人那里得到了很好的解释,我试图将它重新应用于我的情况,我希望它帮忙!

【问题讨论】:

  • 嗯,你得到了错误:你不能访问BrowserWindowdocument。这必须在渲染器进程中完成,即在 HTML 附加到的同一 BrowserWindow 中。
  • @AlexanderLeithner 考虑到我刚刚在孩子中加载了该文档,我将如何通过渲染器进程执行此操作?
  • 例如,您可以在浏览器窗口中加载的 html 文件中包含对脚本的引用。在这个脚本中添加你想要做的关于你的窗口渲染的所有事情。这也与主要的编排和系统接口分开关注。

标签: javascript html electron


【解决方案1】:

我认为最好将渲染器进程视为由它加载的 html 文件(css/js/images 等)链接的所有文件。主进程“控制”渲染器进程,因为它可以打开、关闭它并向它发送消息。渲染器进程本身只是在显示该渲染器进程时运行的 html。

您的方案似乎可以正常工作,但要记住以下一般规则:

  • 任何时候您想提取或插入数据到 html 中,都必须由该 html 中包含的文件(带有脚本标签)处理
  • 如果要在不同的浏览器窗口之间发送数据,必须使用主进程(通常是main.js)作为它们之间的通信层
  • 所有浏览器窗口都将使用 ipcRenderer 模块,因此独特的消息可让您确定(在 main.js 中)它们来自哪里或要去哪里
  • 主进程将使用 ipcMain.on() 捕获每个 ipcRenderer.send()

下面是一些从一个浏览器窗口向另一个窗口发送信息的示例代码:

popup.html

<body>
    some html ....

    <script>
        { ipcRenderer } = require('electron')
        ipcRenderer.send("popup-message", "this is a message")
    </script>
</body>

main.js

ipcMain.on('popup-message', (msg) => {
    mainWindow.webContents.send('popup-message-from-main', msg)
})

index.html(由 mainWindow 加载)

<body>
    some html ....

    <script>
        { ipcRenderer } = require('electron')
        ipcRenderer.on('popup-message-from-main', (msg) => {
            // do something with msg
        })
    </script>
</body>

(可以通过等待 popup.html 中的输入然后将其发送到 main.js 来修改您的示例)

【讨论】:

    猜你喜欢
    • 2017-12-09
    • 2018-05-20
    • 1970-01-01
    • 1970-01-01
    • 2017-07-31
    • 2019-02-05
    • 1970-01-01
    • 2017-12-23
    • 2017-12-05
    相关资源
    最近更新 更多