Wie greife ich auf DOM-Elemente in Elektronen zu?

73

Ich versuche, einer Schaltfläche in einer index.htmlDatei folgende Funktionen hinzuzufügen : Ich habe ein Schaltflächenelement inindex.html

<button id="auth-button">Authorize</button>

In main.jsder App habe ich

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;
    });
});

Ein Fehler tritt jedoch wie folgt auf: Uncaught Exception: ReferenceError: document is not defined

Kann auf die DOM-Objekte zugegriffen werden, während Elektronen-Apps erstellt werden? oder gibt es eine andere alternative Möglichkeit, die mir die erforderliche Funktionalität bietet?

ant_1618
quelle
2
Der Hauptprozess hat keinen Zugriff auf das DOM, sondern der Renderer hat Zugriff. Lernen Sie den Unterschied
Ben Fortune
Können Sie Ihre index.html hier
einfügen

Antworten:

80

Auf DOM kann im Hauptprozess nicht zugegriffen werden, nur in dem Renderer, zu dem es gehört.

Es gibt ein ipcModul, das sowohl für den Hauptprozess als auch für den Renderer-Prozess verfügbar ist und die Kommunikation zwischen diesen beiden über Synchronisierungs- / Asynchronisierungsnachrichten ermöglicht.

Sie können das Remote- Modul auch verwenden, um die Hauptprozess-API vom Renderer aufzurufen, aber es gibt nichts, was es Ihnen erlauben würde, es umgekehrt zu tun.

Wenn Sie im Hauptprozess etwas als Antwort auf eine Benutzeraktion ausführen müssen, verwenden Sie das ipcModul, um die Funktion aufzurufen. Anschließend können Sie ein Ergebnis an den Renderer zurückgeben, auch mit ipc.

Code aktualisiert, um die tatsächliche (v0.37.8) API widerzuspiegeln, wie @Wolfgang im Kommentar vorgeschlagen hat, siehe Bearbeitungsverlauf für veraltete API, wenn Sie mit einer älteren Version von Electron nicht weiterkommen.

Beispielskript in 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');
});

Und im Hauptprozess:

var ipc = require('electron').ipcMain;

ipc.on('invokeAction', function(event, data){
    var result = processData(data);
    event.sender.send('actionReply', result);
});
ROAL
quelle
1
Wenn ich require in index.html verwende, wird der folgende Fehler angezeigt. "Irgendeine Uncaught ReferenceError: require is not definedIdee warum?
ant_1618
Anscheinend haben Sie vergessen, den Fehler einzuschließen. Ich habe derzeit keinen Zugriff auf Elektronen, aber ich denke, require()sollte im Renderer-Prozess verfügbar sein. Edit: OK es ist jetzt hier.
ROAL
@ ant_1618 Welche Version von Electron verwenden Sie? Auch auf welchem ​​Betriebssystem?
ROAL
Verwenden von io.js v2.3.1 und Electron 0.29.1 Unter Linux 15.04
ant_1618
2
@ROAL: Ja, es ist tatsächlich möglich zu verwenden .once(). Electron IPC ist ein Standard Node.js EventEmitter . Auch require('ipc')wurde abgeschrieben, es ist jetzt require('electron').ipcMainund require('electron').ipcRenderer.
Wolfgang
23

Sie können die API webContents.executeJavaScript (Code [, UserGesture, Callback]) verwenden , um JavaScript-Code auszuführen.

zum Beispiel:

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);
});
cuixiping
quelle
2
Am besten lassen Sie dabei niemals Benutzereingaben oder externe Daten zu.
Cooper
9

Wie in diesem Tutorial angegeben :

In Electron gibt es verschiedene Möglichkeiten, zwischen dem Hauptprozess und den Renderer-Prozessen zu kommunizieren, z. B. ipcRenderer- und ipcMain-Module zum Senden von Nachrichten und das Remote-Modul für die Kommunikation im RPC-Stil.

Sie können dem Beispiel also unter https://github.com/electron/electron-api-demos folgen . Sie sollten jsfür jede eine Datei haben html. In dieser jsDatei können Sie jederzeit verwenden require.

Code in 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
})

Code in 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>
onmyway133
quelle