如何访问电子中的DOM个元素?
How to access DOM elements in electron?
我正在尝试向 index.html
文件中的按钮添加功能,如下所示:
我在 index.html
中有一个按钮元素
<button id="auth-button">Authorize</button>
在应用程序的 main.js
中,我有
require('crash-reporter').start();
console.log("oh yaeh!");
var mainWindow = null;
app.on('window-all-closed', function(){
if(process.platform != 'darwin'){
app.quit();
}
});
app.on('ready',function(){
mainWindow = new BrowserWindow({width:800, height : 600});
mainWindow.loadUrl('file://' + __dirname + '/index.html');
var authButton = document.getElementById("auth-button");
authButton.addEventListener("click",function(){alert("clicked!");});
mainWindow.openDevTools();
mainWindow.on('closed',function(){
mainWindow = null;
});
});
但是出现如下错误:
Uncaught Exception: ReferenceError: document is not defined
构建电子应用程序时可以访问 DOM 对象吗?还是有任何其他替代方法可以为我提供所需的功能?
DOM在主进程中不能访问,只能在所属的渲染器中访问。
在 main process as well as the renderer process 上有一个 ipc
模块,允许通过 sync/async 消息在这两者之间进行通信。
您也可以使用 remote 模块从渲染器调用主进程 API,但没有什么可以让您以相反的方式进行。
如果你需要在主进程中运行一些东西作为对用户操作的响应,使用ipc
模块来调用该函数,那么你可以return一个结果来渲染器,也使用 ipc
.
代码已更新以反映实际情况 (v0.37.8) API,正如@Wolfgang 在评论中所建议的那样,如果您坚持使用旧版本,请参阅已弃用 API 的编辑历史记录Electron 版本。
index.html
中的示例脚本:
var ipc = require('electron').ipcRenderer;
var authButton = document.getElementById('auth-button');
authButton.addEventListener('click', function(){
ipc.once('actionReply', function(event, response){
processResponse(response);
})
ipc.send('invokeAction', 'someData');
});
并且在主进程中:
var ipc = require('electron').ipcMain;
ipc.on('invokeAction', function(event, data){
var result = processData(data);
event.sender.send('actionReply', result);
});
您可以使用 webContents.executeJavaScript(code[, userGesture, callback]) API 来执行 JavaScript 代码。
例如:
mainWindow.loadUrl('file://' + __dirname + '/index.html');
mainWindow.webContents.on('did-finish-load', ()=>{
let code = `var authButton = document.getElementById("auth-button");
authButton.addEventListener("click",function(){alert("clicked!");});`;
mainWindow.webContents.executeJavaScript(code);
});
如this tutorial所述:
In Electron, we have several ways to communicate between the main process and renderer processes, such as ipcRenderer and ipcMain modules for sending messages, and the remote module for RPC style communication.
因此您可以按照 https://github.com/electron/electron-api-demos 中的示例进行操作。每个 html
应该有一个 js
文件。在那个 js
文件中,您可以随时使用 require
。
renderer.js
中的代码:
const ipc = require('electron').ipcRenderer
const asyncMsgBtn = document.getElementById('async-msg')
asyncMsgBtn.addEventListener('click', function () {
ipc.send('asynchronous-message', 'ping')
})
ipc.on('asynchronous-reply', function (event, arg) {
const message = `Asynchronous message reply: ${arg}`
document.getElementById('async-reply').innerHTML = message
})
ipc.html
中的代码:
<script type="text/javascript">
require('./renderer-process/communication/sync-msg')
require('./renderer-process/communication/async-msg')
require('./renderer-process/communication/invisible-msg')
</script>
在我的例子中,window 是通过调用 window.open
创建的
默认情况下电子 NodeIntegration 是禁用的,所以你不能访问另一个 window 的 DOM。
将 属性 nativeWindowOpen
更改为 true 解决了我的问题。
// in main.ts
async function createWindow() {
const win = new BrowserWindow({
// ....
webPreferences: {
nativeWindowOpen: true,
}
})
现在我可以在使用 window.open
创建 window 时访问 window.document 元素
我正在尝试向 index.html
文件中的按钮添加功能,如下所示:
我在 index.html
<button id="auth-button">Authorize</button>
在应用程序的 main.js
中,我有
require('crash-reporter').start();
console.log("oh yaeh!");
var mainWindow = null;
app.on('window-all-closed', function(){
if(process.platform != 'darwin'){
app.quit();
}
});
app.on('ready',function(){
mainWindow = new BrowserWindow({width:800, height : 600});
mainWindow.loadUrl('file://' + __dirname + '/index.html');
var authButton = document.getElementById("auth-button");
authButton.addEventListener("click",function(){alert("clicked!");});
mainWindow.openDevTools();
mainWindow.on('closed',function(){
mainWindow = null;
});
});
但是出现如下错误:
Uncaught Exception: ReferenceError: document is not defined
构建电子应用程序时可以访问 DOM 对象吗?还是有任何其他替代方法可以为我提供所需的功能?
DOM在主进程中不能访问,只能在所属的渲染器中访问。
在 main process as well as the renderer process 上有一个 ipc
模块,允许通过 sync/async 消息在这两者之间进行通信。
您也可以使用 remote 模块从渲染器调用主进程 API,但没有什么可以让您以相反的方式进行。
如果你需要在主进程中运行一些东西作为对用户操作的响应,使用ipc
模块来调用该函数,那么你可以return一个结果来渲染器,也使用 ipc
.
代码已更新以反映实际情况 (v0.37.8) API,正如@Wolfgang 在评论中所建议的那样,如果您坚持使用旧版本,请参阅已弃用 API 的编辑历史记录Electron 版本。
index.html
中的示例脚本:
var ipc = require('electron').ipcRenderer;
var authButton = document.getElementById('auth-button');
authButton.addEventListener('click', function(){
ipc.once('actionReply', function(event, response){
processResponse(response);
})
ipc.send('invokeAction', 'someData');
});
并且在主进程中:
var ipc = require('electron').ipcMain;
ipc.on('invokeAction', function(event, data){
var result = processData(data);
event.sender.send('actionReply', result);
});
您可以使用 webContents.executeJavaScript(code[, userGesture, callback]) API 来执行 JavaScript 代码。
例如:
mainWindow.loadUrl('file://' + __dirname + '/index.html');
mainWindow.webContents.on('did-finish-load', ()=>{
let code = `var authButton = document.getElementById("auth-button");
authButton.addEventListener("click",function(){alert("clicked!");});`;
mainWindow.webContents.executeJavaScript(code);
});
如this tutorial所述:
In Electron, we have several ways to communicate between the main process and renderer processes, such as ipcRenderer and ipcMain modules for sending messages, and the remote module for RPC style communication.
因此您可以按照 https://github.com/electron/electron-api-demos 中的示例进行操作。每个 html
应该有一个 js
文件。在那个 js
文件中,您可以随时使用 require
。
renderer.js
中的代码:
const ipc = require('electron').ipcRenderer
const asyncMsgBtn = document.getElementById('async-msg')
asyncMsgBtn.addEventListener('click', function () {
ipc.send('asynchronous-message', 'ping')
})
ipc.on('asynchronous-reply', function (event, arg) {
const message = `Asynchronous message reply: ${arg}`
document.getElementById('async-reply').innerHTML = message
})
ipc.html
中的代码:
<script type="text/javascript">
require('./renderer-process/communication/sync-msg')
require('./renderer-process/communication/async-msg')
require('./renderer-process/communication/invisible-msg')
</script>
在我的例子中,window 是通过调用 window.open
创建的
默认情况下电子 NodeIntegration 是禁用的,所以你不能访问另一个 window 的 DOM。
将 属性 nativeWindowOpen
更改为 true 解决了我的问题。
// in main.ts
async function createWindow() {
const win = new BrowserWindow({
// ....
webPreferences: {
nativeWindowOpen: true,
}
})
现在我可以在使用 window.open