Uwaga
Dostęp do tej strony wymaga autoryzacji. Może spróbować zalogować się lub zmienić katalogi.
Dostęp do tej strony wymaga autoryzacji. Możesz spróbować zmienić katalogi.
Uwaga / Notatka
Nie jest to najnowsza wersja tego artykułu. Aby zapoznać się z bieżącą wersją, przeczytaj artykuł w wersji .NET 9.
Ostrzeżenie
Ta wersja ASP.NET Core nie jest już obsługiwana. Aby uzyskać więcej informacji, zobacz zasady pomocy technicznej platformy .NET i platformy .NET Core. Aby zapoznać się z bieżącą wersją, przeczytaj artykuł w wersji .NET 9.
Ważne
Te informacje odnoszą się do produktu w wersji wstępnej, który może zostać znacząco zmodyfikowany, zanim zostanie wydany komercyjnie. Firma Microsoft nie udziela żadnych gwarancji, wyraźnych ani domniemanych, w odniesieniu do podanych tutaj informacji.
Aby zapoznać się z bieżącą wersją, przeczytaj artykuł w wersji .NET 9.
Wywołania między platformami .NET i JavaScript wymagają dodatkowych obciążeń, ponieważ:
- Wywołania są asynchroniczne.
- Parametry i wartości zwracane są serializowane w formacie JSON, aby zapewnić łatwy do zrozumienia mechanizm konwersji między typami .NET i JavaScript.
Ponadto w przypadku aplikacji po stronie Blazor serwera te wywołania są przekazywane przez sieć.
Unikaj nadmiernie precyzyjnych wywołań
Ponieważ każde wywołanie wiąże się z pewnym obciążeniem, warto zmniejszyć liczbę wywołań. Rozważmy następujący kod, który przechowuje kolekcję elementów w przeglądarce localStorage
:
private async Task StoreAllInLocalStorage(IEnumerable<TodoItem> items)
{
foreach (var item in items)
{
await JS.InvokeVoidAsync("localStorage.setItem", item.Id,
JsonSerializer.Serialize(item));
}
}
W poprzednim przykładzie jest oddzielne JS wywołanie międzyoperajności dla każdego elementu. Zamiast tego następujące podejście zmniejsza JS międzyoperajności do jednego wywołania:
private async Task StoreAllInLocalStorage(IEnumerable<TodoItem> items)
{
await JS.InvokeVoidAsync("storeAllInLocalStorage", items);
}
Odpowiadająca mu funkcja JavaScript przechowuje całą kolekcję elementów na kliencie:
function storeAllInLocalStorage(items) {
items.forEach(item => {
localStorage.setItem(item.id, JSON.stringify(item));
});
}
W przypadku Blazor WebAssembly aplikacji stopniowe pojedyncze JS wywołania międzyoperacyjne w jednym wywołaniu zwykle znacznie poprawia wydajność tylko wtedy, gdy składnik wykonuje dużą liczbę wywołań międzyoperacyjnych JS .
Rozważ użycie wywołań synchronicznych
Wywoływanie kodu JavaScript z platformy .NET
Ta sekcja dotyczy tylko składników po stronie klienta.
JS wywołania międzyoperacyjne są asynchroniczne, niezależnie od tego, czy wywoływany kod jest synchroniczny, czy asynchroniczny. Wywołania są asynchroniczne, aby zapewnić zgodność komponentów z trybami renderowania po stronie serwera i klienta. Na serwerze wszystkie JS wywołania międzyoperacyjne muszą być asynchroniczne, ponieważ są wysyłane za pośrednictwem połączenia sieciowego.
Jeśli z całą pewnością wiesz, że twój komponent działa tylko na WebAssembly, możesz zdecydować się na synchroniczne wywołania międzyoperacyjne JS. Ma to nieco mniejsze obciążenie niż wykonywanie wywołań asynchronicznych i może spowodować zmniejszenie liczby cykli renderowania, ponieważ nie ma stanu pośredniego podczas oczekiwania na wyniki.
Aby wykonać synchroniczne wywołanie z platformy .NET do języka JavaScript w składniku po stronie klienta, rzutuj IJSRuntime na IJSInProcessRuntime, aby wywołać interfejs współpracy JS.
@inject IJSRuntime JS
...
@code {
protected override void HandleSomeEvent()
{
var jsInProcess = (IJSInProcessRuntime)JS;
var value = jsInProcess.Invoke<string>("javascriptFunctionIdentifier");
}
}
Podczas pracy ze składnikami IJSObjectReference po stronie klienta platformy .NET 5 lub nowszej można użyć IJSInProcessObjectReference synchronicznie. IJSInProcessObjectReference implementuje IAsyncDisposable/IDisposable i powinien być usunięty do odzyskiwania pamięci, aby zapobiec wyciekowi pamięci, jak pokazano w poniższym przykładzie:
@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();
}
}
}
W poprzednim przykładzie element JSDisconnectedException nie jest uwięziony podczas usuwania modułu, ponieważ w aplikacji Blazor nie ma obwodu SignalR-Blazor WebAssembly, który można utracić. Aby uzyskać więcej informacji, zobacz ASP.NET Core Blazor JavaScript interoperability (JS interop).
Wywoływanie platformy .NET ze środowiska JavaScript
Ta sekcja dotyczy tylko składników po stronie klienta.
JS wywołania międzyoperacyjne są asynchroniczne, niezależnie od tego, czy wywoływany kod jest synchroniczny, czy asynchroniczny. Wywołania są asynchroniczne, aby zapewnić zgodność komponentów z trybami renderowania po stronie serwera i klienta. Na serwerze wszystkie JS wywołania międzyoperacyjne muszą być asynchroniczne, ponieważ są wysyłane za pośrednictwem połączenia sieciowego.
Jeśli z całą pewnością wiesz, że twój komponent działa tylko na WebAssembly, możesz zdecydować się na synchroniczne wywołania międzyoperacyjne JS. Ma to nieco mniejsze obciążenie niż wykonywanie wywołań asynchronicznych i może spowodować zmniejszenie liczby cykli renderowania, ponieważ nie ma stanu pośredniego podczas oczekiwania na wyniki.
Aby wykonać wywołanie synchroniczne z języka JavaScript do platformy .NET w składniku po stronie klienta, użyj polecenia DotNet.invokeMethod
zamiast DotNet.invokeMethodAsync
.
Wywołania synchroniczne działają, jeśli:
Ta sekcja dotyczy tylko składników po stronie klienta.
JS wywołania międzyoperacyjne są asynchroniczne, niezależnie od tego, czy wywoływany kod jest synchroniczny, czy asynchroniczny. Wywołania są asynchroniczne, aby zapewnić zgodność komponentów z trybami renderowania po stronie serwera i klienta. Na serwerze wszystkie JS wywołania międzyoperacyjne muszą być asynchroniczne, ponieważ są wysyłane za pośrednictwem połączenia sieciowego.
Jeśli z całą pewnością wiesz, że twój komponent działa tylko na WebAssembly, możesz zdecydować się na synchroniczne wywołania międzyoperacyjne JS. Ma to nieco mniejsze obciążenie niż wykonywanie wywołań asynchronicznych i może spowodować zmniejszenie liczby cykli renderowania, ponieważ nie ma stanu pośredniego podczas oczekiwania na wyniki.
Aby wykonać synchroniczne wywołanie z platformy .NET do języka JavaScript w składniku po stronie klienta, rzutuj IJSRuntime na IJSInProcessRuntime, aby wywołać interfejs współpracy JS.
@inject IJSRuntime JS
...
@code {
protected override void HandleSomeEvent()
{
var jsInProcess = (IJSInProcessRuntime)JS;
var value = jsInProcess.Invoke<string>("javascriptFunctionIdentifier");
}
}
Podczas pracy ze składnikami IJSObjectReference po stronie klienta platformy .NET 5 lub nowszej można użyć IJSInProcessObjectReference synchronicznie. IJSInProcessObjectReference implementuje IAsyncDisposable/IDisposable i powinien być usunięty do odzyskiwania pamięci, aby zapobiec wyciekowi pamięci, jak pokazano w poniższym przykładzie:
@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();
}
}
}
W poprzednim przykładzie element JSDisconnectedException nie jest uwięziony podczas usuwania modułu, ponieważ w aplikacji Blazor nie ma obwodu SignalR-Blazor WebAssembly, który można utracić. Aby uzyskać więcej informacji, zobacz ASP.NET Core Blazor JavaScript interoperability (JS interop).
Rozważ użycie niezamężnych połączeń
Ta sekcja dotyczy Blazor WebAssembly tylko aplikacji.
W przypadku uruchamiania w systemie Blazor WebAssemblymożna wykonać niezamężne wywołania z platformy .NET do języka JavaScript. Są to synchroniczne wywołania, które nie wykonują serializacji JSON argumentów ani zwracanych wartości. Wszystkie aspekty zarządzania pamięcią i tłumaczenia między reprezentacjami platformy .NET i języka JavaScript są pozostawione deweloperowi.
Ostrzeżenie
Chociaż użycie IJSUnmarshalledRuntime ma najmniejsze obciążenie związane z JS podejściami międzyoperacyjnymi, interfejsy API języka JavaScript wymagane do interakcji z tymi interfejsami API są obecnie nieudokumentowane i podlegają zmianom powodującym niezgodność w przyszłych wersjach.
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");
}
}
Korzystanie z międzyoperacji języka JavaScript [JSImport]
/[JSExport]
Współdziałanie języka JavaScript [JSImport]
/[JSExport]
dla Blazor WebAssembly aplikacji zapewnia lepszą wydajność i stabilność interfejsu API międzyoperacyjnego JS w wersjach platformy przed ASP.NET Core na platformie .NET 7.
Aby uzyskać więcej informacji, zobacz JavaScript JSImport/JSExport interop with ASP.NET Core (Interopcja javaScript JSImport/JSExport with ASP.NET Core Blazor).