Hinweis
Für den Zugriff auf diese Seite ist eine Autorisierung erforderlich. Sie können versuchen, sich anzumelden oder das Verzeichnis zu wechseln.
Für den Zugriff auf diese Seite ist eine Autorisierung erforderlich. Sie können versuchen, das Verzeichnis zu wechseln.
Hinweis
Dies ist nicht die neueste Version dieses Artikels. Die aktuelle Version finden Sie in der .NET 10-Version dieses Artikels.
Warnung
Diese Version von ASP.NET Core wird nicht mehr unterstützt. Weitere Informationen finden Sie in der .NET- und .NET Core-Supportrichtlinie. Informationen zum aktuellen Release finden Sie in der .NET 9-Version dieses Artikels.
Aufrufe zwischen .NET und JavaScript erfordern zusätzlichen Aufwand, da:
- Aufrufe sind asynchron.
- Parameter und Rückgabewerte werden JSON-serialisiert, um einen leicht verständlichen Konvertierungsmechanismus zwischen .NET- und JavaScript-Typen bereitzustellen.
Darüber hinaus werden diese Aufrufe für serverseitige Blazor Apps über das Netzwerk weitergegeben.
Vermeiden Sie übermäßige feingliedrige Anfragen
Da jeder Anruf einen gewissen Aufwand erfordert, kann es hilfreich sein, die Anzahl der Anrufe zu reduzieren. Beachten Sie den folgenden Code, der eine Sammlung von Elementen im Browser localStoragespeichert:
private async Task StoreAllInLocalStorage(IEnumerable<TodoItem> items)
{
foreach (var item in items)
{
await JS.InvokeVoidAsync("localStorage.setItem", item.Id,
JsonSerializer.Serialize(item));
}
}
Im vorherigen Beispiel wird für jedes Element ein separater JS Interoperabilitätsaufruf ausgeführt. Stattdessen wird der JS-Interop durch den folgenden Ansatz auf nur einen einzigen Aufruf reduziert:
private async Task StoreAllInLocalStorage(IEnumerable<TodoItem> items)
{
await JS.InvokeVoidAsync("storeAllInLocalStorage", items);
}
Die entsprechende JavaScript-Funktion speichert die gesamte Sammlung von Elementen auf dem Client:
function storeAllInLocalStorage(items) {
items.forEach(item => {
localStorage.setItem(item.id, JSON.stringify(item));
});
}
Bei Blazor WebAssembly Apps verbessert das Zusammenfassen einzelner JS Interoperabilitätsaufrufe zu einem einzigen Aufruf die Leistung in der Regel nur dann erheblich, wenn die Komponente eine große Anzahl von JS Interopaufrufen vornimmt.
Berücksichtigen Sie die Verwendung synchroner Aufrufe.
Aufruf von JavaScript in .NET
Dieser Abschnitt gilt nur für clientseitige Komponenten.
JS Interoperabilitätsaufrufe sind asynchron, unabhängig davon, ob der aufgerufene Code synchron oder asynchron ist. Die Aufrufe sind asynchron, um sicherzustellen, dass die Komponenten mit den serverseitigen und clientseitigen Rendermodi kompatibel sind. Auf dem Server müssen alle JS-Interop-Aufrufe asynchron sein, da sie über eine Netzwerkverbindung gesendet werden.
Wenn Ihre Komponente ausschließlich in WebAssembly ausgeführt wird, können Sie sich für synchrone JS-Interop-Aufrufe entscheiden. Dies ist mit etwas weniger Mehraufwand verbunden als asynchrone Aufrufe und kann zu weniger Renderingzyklen führen, da es keinen Zwischenzustand gibt, während auf die Ergebnisse gewartet wird.
Um in einer clientseitigen Komponente einen synchronen Aufruf von .NET an JavaScript zu richten, wandeln Sie IJSRuntime in IJSInProcessRuntime um, um den JS-Interop-Aufruf auszuführen:
@inject IJSRuntime JS
...
@code {
protected override void HandleSomeEvent()
{
var jsInProcess = (IJSInProcessRuntime)JS;
var value = jsInProcess.Invoke<string>("javascriptFunctionIdentifier");
}
}
Mit IJSObjectReference in .NET 5 oder späteren clientseitigen Komponenten können Sie stattdessen IJSInProcessObjectReference synchron verwenden. IJSInProcessObjectReference implementiert IAsyncDisposable/IDisposable und sollte für die Garbage Collection entsorgt werden, um ein Speicherleck zu vermeiden, wie das folgende Beispiel zeigt:
@inject IJSRuntime JS
@implements IDisposable
...
@code {
...
private IJSInProcessObjectReference? module;
protected override async Task OnAfterRenderAsync(bool firstRender)
{
if (firstRender)
{
var jsInProcess = (IJSInProcessRuntime)JS;
module = await jsInProcess.Invoke<IJSInProcessObjectReference>("import",
"./scripts.js");
var value = module.Invoke<string>("javascriptFunctionIdentifier");
}
}
...
void IDisposable.Dispose()
{
if (module is not null)
{
await module.Dispose();
}
}
}
Im vorangegangenen Beispiel ist ein JSDisconnectedException bei der Modulentsorgung nicht gefangen, weil es keine Blazor-SignalR -Schaltung in einer Blazor WebAssembly -App zu verlieren gibt. Weitere Informationen finden Sie unter ASP.NET Core Blazor JavaScript-Interoperabilität (JS Interop).
Aufrufen von .NET aus JavaScript
Dieser Abschnitt gilt nur für clientseitige Komponenten.
JS Interoperabilitätsaufrufe sind asynchron, unabhängig davon, ob der aufgerufene Code synchron oder asynchron ist. Die Aufrufe sind asynchron, um sicherzustellen, dass die Komponenten mit den serverseitigen und clientseitigen Rendermodi kompatibel sind. Auf dem Server müssen alle JS-Interop-Aufrufe asynchron sein, da sie über eine Netzwerkverbindung gesendet werden.
Wenn Ihre Komponente ausschließlich in WebAssembly ausgeführt wird, können Sie sich für synchrone JS-Interop-Aufrufe entscheiden. Dies ist mit etwas weniger Mehraufwand verbunden als asynchrone Aufrufe und kann zu weniger Renderingzyklen führen, da es keinen Zwischenzustand gibt, während auf die Ergebnisse gewartet wird.
Um einen synchronen Aufruf von JavaScript zu .NET in einer clientseitigen Komponente auszuführen, verwenden Sie DotNet.invokeMethod anstelle von DotNet.invokeMethodAsync.
Synchrone Aufrufe funktionieren, wenn:
Dieser Abschnitt gilt nur für clientseitige Komponenten.
JS Interoperabilitätsaufrufe sind asynchron, unabhängig davon, ob der aufgerufene Code synchron oder asynchron ist. Die Aufrufe sind asynchron, um sicherzustellen, dass die Komponenten mit den serverseitigen und clientseitigen Rendermodi kompatibel sind. Auf dem Server müssen alle JS-Interop-Aufrufe asynchron sein, da sie über eine Netzwerkverbindung gesendet werden.
Wenn Ihre Komponente ausschließlich in WebAssembly ausgeführt wird, können Sie sich für synchrone JS-Interop-Aufrufe entscheiden. Dies ist mit etwas weniger Mehraufwand verbunden als asynchrone Aufrufe und kann zu weniger Renderingzyklen führen, da es keinen Zwischenzustand gibt, während auf die Ergebnisse gewartet wird.
Um in einer clientseitigen Komponente einen synchronen Aufruf von .NET an JavaScript zu richten, wandeln Sie IJSRuntime in IJSInProcessRuntime um, um den JS-Interop-Aufruf auszuführen:
@inject IJSRuntime JS
...
@code {
protected override void HandleSomeEvent()
{
var jsInProcess = (IJSInProcessRuntime)JS;
var value = jsInProcess.Invoke<string>("javascriptFunctionIdentifier");
}
}
Mit IJSObjectReference in .NET 5 oder späteren clientseitigen Komponenten können Sie stattdessen IJSInProcessObjectReference synchron verwenden. IJSInProcessObjectReference implementiert IAsyncDisposable/IDisposable und sollte für die Garbage Collection entsorgt werden, um ein Speicherleck zu vermeiden, wie das folgende Beispiel zeigt:
@inject IJSRuntime JS
@implements IDisposable
...
@code {
...
private IJSInProcessObjectReference? module;
protected override async Task OnAfterRenderAsync(bool firstRender)
{
if (firstRender)
{
var jsInProcess = (IJSInProcessRuntime)JS;
module = await jsInProcess.Invoke<IJSInProcessObjectReference>("import",
"./scripts.js");
var value = module.Invoke<string>("javascriptFunctionIdentifier");
}
}
...
void IDisposable.Dispose()
{
if (module is not null)
{
await module.Dispose();
}
}
}
Im vorangegangenen Beispiel ist ein JSDisconnectedException bei der Modulentsorgung nicht gefangen, weil es keine Blazor-SignalR -Schaltung in einer Blazor WebAssembly -App zu verlieren gibt. Weitere Informationen finden Sie unter ASP.NET Core Blazor JavaScript-Interoperabilität (JS Interop).
Erwägen Sie die Verwendung von nicht gemarshalleden Anrufen
Dieser Abschnitt gilt nur für Blazor WebAssembly Apps.
Bei der Ausführung von Blazor WebAssembly ist es möglich, nicht-marshallierte Aufrufe von .NET zu JavaScript durchzuführen. Hierbei handelt es sich um synchrone Aufrufe, die keine JSON-Serialisierung von Argumenten oder Rückgabewerten ausführen. Alle Aspekte der Speicherverwaltung und Übersetzungen zwischen .NET- und JavaScript-Darstellungen bleiben dem Entwickler überlassen.
Warnung
Während die Verwendung von IJSUnmarshalledRuntime den geringsten Aufwand unter den JS Interoperabilitätsansätzen erfordert, sind die JavaScript-APIs, die für die Interaktion mit diesen APIs erforderlich sind, derzeit nicht dokumentiert und können in zukünftigen Veröffentlichungen Änderungen unterworfen sein.
function jsInteropCall() {
return BINDING.js_to_mono_obj("Hello world");
}
@inject IJSRuntime JS
@code {
protected override void OnInitialized()
{
var unmarshalledJs = (IJSUnmarshalledRuntime)JS;
var value = unmarshalledJs.InvokeUnmarshalled<string>("jsInteropCall");
}
}
Verwenden Sie JavaScript-Interop [JSImport]/[JSExport]
JavaScript-Interop [JSImport]/[JSExport] für Blazor WebAssembly-Apps bietet verbesserte Leistung und Stabilität gegenüber der JS-Interop-API in Framework-Versionen vor ASP.NET Core in .NET 7.
Weitere Informationen finden Sie unter JavaScript-Interoperabilität durch JSImport/JSExport mit ASP.NET Core-Blazor.