Execute JavaScript
webforJ läuft auf dem Server, aber es gibt Zeiten, in denen Sie den Client erreichen müssen: das Fenster scrollen, ein Feld fokussieren, einen Wert des Browsers lesen oder eine Methode auf einer Web-Komponente aufrufen. Die HasJsExecution Schnittstelle bietet diese Brücke. Sie wird auf zwei Ebenen implementiert:
- Die
Pageführt Skripte im Kontext der gesamten Seite aus. - Ein
Elementführt Skripte, die auf ein einzelnes Client-Element beschränkt sind, aus.
Beide stellen die gleichen drei Methoden bereit, sodass sie, wenn Sie die Formen unten kennen, unabhängig davon, ob Sie sie auf Page oder einem Element aufrufen, gleich gelesen werden.
Ausführungsmethoden
Jede Ebene bietet eine synchrone Methode und zwei asynchrone Methoden. Der Unterschied liegt darin, ob der aufrufende Thread wartet und ob ein Ergebnis zurückkommt.
-
executeJs(String script): führt das Skript synchron aus. Der ausführende Thread wird blockiert, bis der Client zurückkehrt, was eine Server-zu-Client-Rundreise kostet. Das Ergebnis kommt alsObjectzurück, das Sie in Java casten und verwenden können. -
executeJsAsync(String script): führt das Skript asynchron aus und blockiert nicht den ausführenden Thread. Es gibt einPendingResultzurück, das abgeschlossen wird, wenn das Skript beendet ist, sodass Sie später auf das Ergebnis reagieren können. -
executeJsVoidAsync(String script): führt das Skript asynchron aus und gibt nichts an den Server zurück. Verwenden Sie es für Fire-and-Forget-Arbeiten, bei denen Sie das Ergebnis nicht benötigen. Verfügbar seit24.11.
Greifen Sie standardmäßig auf executeJsVoidAsync zu, wenn Sie nur einen Nebeneffekt auf dem Client verursachen (Scrollen, Fokussieren, eine Methode aufrufen). Verwenden Sie executeJsAsync, wenn Sie den Wert benötigen, aber nicht blockierend bleiben möchten, und reservieren Sie die synchrone executeJs für den seltenen Fall, dass Sie das Ergebnis vor der nächsten Java-Zeile benötigen, da es den Thread für eine volle Rundreise hält.
Ergebnisse lesen
Wenn ein Skript einen Wert zurückgibt, konvertiert webforJ ihn in den entsprechenden Java-Typ:
| JavaScript-Wert | Java-Typ |
|---|---|
| number | Integer, Long oder Double |
| string | String |
| boolean | Boolean |
null oder undefined | null |
| jeder andere Typ | seine Zeichenfolgen-Darstellung |
Lesen Sie Werte mit executeJsAsync, das die Konvertierung zuverlässig anwendet. Eine zurückgegebene Zahl kann als Integer, Long oder Double ankommen, lesen Sie sie daher über Number:
Page.getCurrent()
.executeJsAsync("return window.innerWidth;")
.thenAccept(result -> {
int width = ((Number) result).intValue();
// verwenden Sie width
});
Die synchrone executeJs gibt null zurück, wenn der Ausführungskontext nicht bereit ist, beispielsweise wenn sie aufgerufen wird, bevor die Komponente angeknüpft ist. Verwenden Sie executeJsAsync, wann immer Sie vom zurückgegebenen Wert abhängen, und vermeiden Sie es, ein synchrones Ergebnis an einen bestimmten Typ zu casten.
Ausführung auf Anwendungsebene
Rufen Sie die Methoden auf Page auf, wenn das Skript die gesamte Seite und nicht eine Komponente betrifft. Holen Sie sich die aktuelle Seite mit Page.getCurrent().
Ein häufiger Fall ist das Zurückscrollen nach einem Routenwechsel. Nichts muss zurückkommen, also passt executeJsVoidAsync:
Page.getCurrent().executeJsVoidAsync(
"window.scrollTo({ top: 0, behavior: 'smooth' });");
Wenn Sie einen Client-Wert auf dem Server benötigen, lesen Sie ihn asynchron und handeln Sie, wenn das Ergebnis eintrifft:
Page.getCurrent()
.executeJsAsync("return navigator.language;")
.thenAccept(language -> {
// language ist die Browsersprache, zum Beispiel "en-US"
applyLocale(String.valueOf(language));
});
Verwenden Sie ausführung auf Elementebene, wenn das Skript auf ein bestimmtes Client-Element und nicht auf die gesamte Seite wirken soll.
Im folgenden Demo führt die Auswahl von Link kopieren ein Skript über Page mit executeJsVoidAsync aus, um den Einladungslink in die Zwischenablage des Besuchers zu schreiben. Das Kopieren ist ein Nebeneffekt, der nichts zurückgeben muss, sodass die Fire-and-Forget-Methode gut geeignet ist.
Code anzeigen
- ExecuteJavaScriptView.java
Ausführung auf Elementebene
Wenn Sie die gleichen Methoden auf einem Element aufrufen, wird das Skript auf dieses Element anstelle der Seite beschränkt. Die Rückgabewerte sowie das synchrone und asynchrone Verhalten sind identisch zu den vorhergehenden Methoden auf Seitenebene.
Element-Skripte werden in die Warteschlange gestellt, bis das Element dem DOM angefügt ist, und laufen dann, sodass Sie sie während des Setups aufrufen können, ohne auf die Anheftung zu warten.
Aufruf einer Funktion auf einem Element
Wenn Sie eine benannte Client-seitige Funktion aufrufen möchten, anstatt einen Skript-String auszuführen, bietet das Element eine parallele Menge von Methoden. Anstelle eines Skripts übergeben Sie den Funktionsnamen und seine Argumente, die webforJ serialisiert und übergibt. Zwei Argumenttypen werden speziell behandelt: this wird durch das Client-Element ersetzt, und jedes Component-Argument wird durch seine Client-Instanz ersetzt, sobald es angeknüpft ist.
Diese spiegeln die Ausführungsmethoden wider, unterscheiden sich nur darin, ob der Thread wartet und ob ein Ergebnis zurückgegeben wird:
-
callJsFunction(String name, Object... args): ruft die Funktion synchron auf und gibt ihr Ergebnis alsObjectzurück. Der ausführende Thread blockiert für eine Rundreise. -
callJsFunctionAsync(String name, Object... args): ruft die Funktion asynchron ohne Blockierung auf und gibt einPendingResultzurück, das mit dem Ergebnis der Funktion abgeschlossen wird. Verfügbar seit24.11. -
callJsFunctionVoidAsync(String name, Object... args): ruft die Funktion asynchron auf und gibt nichts an den Server zurück. Verwenden Sie es für Fire-and-Forget-Aufrufe, bei denen Sie den Rückgabewert nicht benötigen. Verfügbar seit24.11.
Da der Aufruf wartet, bis jedes Component-Argument angeheftet ist, bevor er ausgeführt wird, wird ein Aufruf, der ein Element übergibt, das niemals angeheftet wird, nie abgeschlossen.
// Fokussieren Sie die Eingabe einer Web-komponente, indem Sie ihre Client-seitige Methode aufrufen
searchElement.callJsFunctionVoidAsync("focus");