Udostępnij za pośrednictwem


Współdziałanie języka JavaScript [JSImport]/[JSExport] z platformą ASP.NET Core Blazor

Uwaga

Nie jest to najnowsza wersja tego artykułu. Aby zapoznać się z bieżącą wersją, zapoznaj się z wersją tego artykułu platformy .NET 8.

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, jawnych lub domniemanych, w odniesieniu do informacji podanych w tym miejscu.

Aby zapoznać się z bieżącą wersją, zapoznaj się z wersją tego artykułu platformy .NET 8.

W tym artykule wyjaśniono, jak korzystać z języka JavaScript (JS) w składnikach po stronie klienta przy użyciu międzyoperacyjnego interfejsu API języka JavaScript (JS) [JSImport]/[JSExport] wydanego dla aplikacji, które przyjmują platformę .NET 7 lub nowszą.

Blazor zapewnia własny JS mechanizm międzyoperacyjny oparty na interfejsie IJSRuntime . BlazorWspółdziałanie JS międzyoperajności jest jednolicie obsługiwane w Blazor trybach renderowania i w przypadku Blazor Hybrid aplikacji. IJSRuntime Umożliwia również autorom bibliotek tworzenie JS bibliotek międzyoperacyjności na potrzeby udostępniania w ekosystemie Blazor i pozostaje zalecanym podejściem do JS międzyoperacyjności w programie Blazor. Odwiedź następujące artykuły:

W tym artykule opisano alternatywne JS podejście międzyoperamentowe specyficzne dla składników po stronie klienta wykonywanych w zestawie WebAssembly. Te podejścia są odpowiednie, gdy oczekujesz, że będzie działać tylko w trybie WebAssembly po stronie klienta. Autorzy bibliotek mogą użyć tych metod optymalizacji JS międzyoperacyjnej, sprawdzając podczas wykonywania kodu, czy aplikacja jest uruchomiona w zestawie WebAssembly w przeglądarce (OperatingSystem.IsBrowser). Metody opisane w tym artykule powinny służyć do zastępowania przestarzałego, niezamężnego JS interfejsu API międzyoperacyjności podczas migracji do platformy .NET 7 lub nowszej.

Uwaga

Ten artykuł koncentruje się na JS współdziałaniu składników po stronie klienta. Aby uzyskać wskazówki dotyczące wywoływania platformy .NET w aplikacjach JavaScript, zobacz Uruchamianie platformy .NET w języku JavaScript.

Przestarzały interfejs API międzyoperacyjny języka JavaScript

Unmarshalled JS interop using IJSUnmarshalledRuntime API is przestarzałe w ASP.NET Core na platformie .NET 7 lub nowszym. Postępuj zgodnie ze wskazówkami w tym artykule, aby zastąpić przestarzały interfejs API.

Wymagania wstępne

Pobierz i zainstaluj program .NET 7 lub nowszy , jeśli nie został jeszcze zainstalowany w systemie lub jeśli system nie ma zainstalowanej najnowszej wersji.

Przestrzeń nazw

Interfejs JS API międzyoperacyjnych opisany w tym artykule jest kontrolowany przez atrybuty w System.Runtime.InteropServices.JavaScript przestrzeni nazw.

Włączanie niebezpiecznych bloków

AllowUnsafeBlocks Włącz właściwość w pliku projektu aplikacji, która zezwala generatorowi kodu w kompilatorze Roslyn na używanie wskaźników dla JS międzyoperacyjności:

<PropertyGroup>
  <AllowUnsafeBlocks>true</AllowUnsafeBlocks>
</PropertyGroup>

Ostrzeżenie

Interfejs JS API międzyoperajności wymaga włączenia funkcji AllowUnsafeBlocks. Należy zachować ostrożność podczas implementowania własnego niebezpiecznego kodu w aplikacjach platformy .NET, co może powodować zagrożenia bezpieczeństwa i stabilności. Aby uzyskać więcej informacji, zobacz Niebezpieczny kod, typy wskaźników i wskaźniki funkcji.

Wywoływanie kodu JavaScript z platformy .NET

W tej sekcji opisano sposób wywoływania JS funkcji z platformy .NET.

W poniższym składniku CallJavaScript1:

  • Moduł CallJavaScript1 jest importowany asynchronicznie ze sprowadzonego JS pliku za pomocą polecenia JSHost.ImportAsync.
  • Zaimportowana getMessageJS funkcja jest wywoływana przez GetWelcomeMessagefunkcję .
  • Zwrócony ciąg komunikatu powitalnego jest wyświetlany w interfejsie użytkownika za pośrednictwem message pola.

CallJavaScript1.razor:

@page "/call-javascript-1"
@rendermode InteractiveWebAssembly
@using System.Runtime.InteropServices.JavaScript

<h1>
    JS <code>[JSImport]</code>/<code>[JSExport]</code> Interop 
    (Call JS Example 1)
</h1>

@(message is not null ? message : string.Empty)

@code {
    private string? message;

    protected override async Task OnInitializedAsync()
    {
        await JSHost.ImportAsync("CallJavaScript1", 
            "../Components/Pages/CallJavaScript1.razor.js");

        message = GetWelcomeMessage();
    }
}
@page "/call-javascript-1"
@using System.Runtime.InteropServices.JavaScript

<h1>
    JS <code>[JSImport]</code>/<code>[JSExport]</code> Interop 
    (Call JS Example 1)
</h1>

@(message is not null ? message : string.Empty)

@code {
    private string? message;

    protected override async Task OnInitializedAsync()
    {
        await JSHost.ImportAsync("CallJavaScript1", 
            "../Pages/CallJavaScript1.razor.js");

        message = GetWelcomeMessage();
    }
}

Uwaga

Dołącz kod OperatingSystem.IsBrowser sprawdzania warunkowego, aby upewnić się, że JS interop jest wywoływany tylko przez składnik renderowany na kliencie. Jest to ważne w przypadku bibliotek/pakietów NuGet przeznaczonych dla składników po stronie serwera, które nie mogą wykonać kodu dostarczonego przez ten JS interfejs API międzyoperacyjnej.

Aby zaimportować JS funkcję w celu wywołania jej z języka C#, użyj atrybutu[JSImport] w podpisie metody języka C#, który pasuje do JS podpisu funkcji. Pierwszy parametr atrybutu to nazwa JS funkcji do zaimportowania, a drugi parametr to nazwa modułuJS.[JSImport]

W poniższym przykładzie jest JS to funkcja, getMessage która zwraca string element dla modułu o nazwie CallJavaScript1. Sygnatura metody języka C#jest zgodna: do funkcji nie są przekazywane JS żadne parametry, a JS funkcja zwraca stringwartość . Funkcja jest wywoływana JS w GetWelcomeMessage kodzie języka C#.

CallJavaScript1.razor.cs:

using System.Runtime.InteropServices.JavaScript;
using System.Runtime.Versioning;

namespace BlazorSample.Components.Pages;

[SupportedOSPlatform("browser")]
public partial class CallJavaScript1
{
    [JSImport("getMessage", "CallJavaScript1")]
    internal static partial string GetWelcomeMessage();
}

Przestrzeń nazw aplikacji dla poprzedniej klasy częściowej CallJavaScript1 to BlazorSample. Przestrzeń nazw składnika to BlazorSample.Components.Pages. Jeśli używasz poprzedniego składnika w lokalnej aplikacji testowej, zaktualizuj przestrzeń nazw tak, aby odpowiadała aplikacji. Na przykład przestrzeń nazw to ContosoApp.Components.Pages , jeśli przestrzeń nazw aplikacji to ContosoApp. Aby uzyskać więcej informacji, zobacz ASP.NET Podstawowe Razor składniki.

using System.Runtime.InteropServices.JavaScript;
using System.Runtime.Versioning;

namespace BlazorSample.Pages;

[SupportedOSPlatform("browser")]
public partial class CallJavaScript1
{
    [JSImport("getMessage", "CallJavaScript1")]
    internal static partial string GetWelcomeMessage();
}

Przestrzeń nazw aplikacji dla poprzedniej klasy częściowej CallJavaScript1 to BlazorSample. Przestrzeń nazw składnika to BlazorSample.Pages. Jeśli używasz poprzedniego składnika w lokalnej aplikacji testowej, zaktualizuj przestrzeń nazw tak, aby odpowiadała aplikacji. Na przykład przestrzeń nazw to ContosoApp.Pages , jeśli przestrzeń nazw aplikacji to ContosoApp. Aby uzyskać więcej informacji, zobacz ASP.NET Podstawowe Razor składniki.

W zaimportowanym podpisie metody można użyć typów platformy .NET dla parametrów i wartości zwracanych, które są automatycznie obsługiwane przez środowisko uruchomieniowe. Służy JSMarshalAsAttribute<T> do kontrolowania sposobu stosowania importowanych parametrów metody. Na przykład możesz wybrać przeprowadzanie marshalingu long jako lub System.Runtime.InteropServices.JavaScript.JSType.BigIntSystem.Runtime.InteropServices.JavaScript.JSType.Number . Wywołania zwrotne można przekazać Action/Func<TResult> jako parametry, które są wywoływane jako funkcje możliwe do wywołania.JS Można przekazać odwołania do JS obiektów zarządzanych i i są one marshalowane jako obiekty proxy, utrzymując obiekt aktywny przez granicę do momentu, aż serwer proxy zostanie odśmiecany. Możesz również importować i eksportować metody asynchroniczne z Task wynikiem, które są marshalowane jako JS obietnice. Większość typów marshaled działa w obu kierunkach, jako parametry i jako wartości zwracane, zarówno w metodach importowanych, jak i eksportowanych, które są omówione w sekcji Wywoływanie platformy .NET z języka JavaScript w dalszej części tego artykułu.

W poniższej tabeli przedstawiono obsługiwane mapowania typów.

.NET JavaScript Nullable Task➔doPromise JSMarshalAs Opcjonalne Array of
Boolean Boolean Obsługiwane Obsługiwane Obsługiwane Nieobsługiwane
Byte Number Obsługiwane Obsługiwane Obsługiwane Obsługiwane
Char String Obsługiwane Obsługiwane Obsługiwane Nieobsługiwane
Int16 Number Obsługiwane Obsługiwane Obsługiwane Nieobsługiwane
Int32 Number Obsługiwane Obsługiwane Obsługiwane Obsługiwane
Int64 Number Obsługiwane Obsługiwane Nieobsługiwane Nieobsługiwane
Int64 BigInt Obsługiwane Obsługiwane Nieobsługiwane Nieobsługiwane
Single Number Obsługiwane Obsługiwane Obsługiwane Nieobsługiwane
Double Number Obsługiwane Obsługiwane Obsługiwane Obsługiwane
IntPtr Number Obsługiwane Obsługiwane Obsługiwane Nieobsługiwane
DateTime Date Obsługiwane Obsługiwane Nieobsługiwane Nieobsługiwane
DateTimeOffset Date Obsługiwane Obsługiwane Nieobsługiwane Nieobsługiwane
Exception Error Nieobsługiwane Obsługiwane Obsługiwane Nieobsługiwane
JSObject Object Nieobsługiwane Obsługiwane Obsługiwane Obsługiwane
String String Nieobsługiwane Obsługiwane Obsługiwane Obsługiwane
Object Any Nieobsługiwane Obsługiwane Nieobsługiwane Obsługiwane
Span<Byte> MemoryView Nieobsługiwane Nieobsługiwane Nieobsługiwane Nieobsługiwane
Span<Int32> MemoryView Nieobsługiwane Nieobsługiwane Nieobsługiwane Nieobsługiwane
Span<Double> MemoryView Nieobsługiwane Nieobsługiwane Nieobsługiwane Nieobsługiwane
ArraySegment<Byte> MemoryView Nieobsługiwane Nieobsługiwane Nieobsługiwane Nieobsługiwane
ArraySegment<Int32> MemoryView Nieobsługiwane Nieobsługiwane Nieobsługiwane Nieobsługiwane
ArraySegment<Double> MemoryView Nieobsługiwane Nieobsługiwane Nieobsługiwane Nieobsługiwane
Task Promise Nieobsługiwane Nieobsługiwane Obsługiwane Nieobsługiwane
Action Function Nieobsługiwane Nieobsługiwane Nieobsługiwane Nieobsługiwane
Action<T1> Function Nieobsługiwane Nieobsługiwane Nieobsługiwane Nieobsługiwane
Action<T1, T2> Function Nieobsługiwane Nieobsługiwane Nieobsługiwane Nieobsługiwane
Action<T1, T2, T3> Function Nieobsługiwane Nieobsługiwane Nieobsługiwane Nieobsługiwane
Func<TResult> Function Nieobsługiwane Nieobsługiwane Nieobsługiwane Nieobsługiwane
Func<T1, TResult> Function Nieobsługiwane Nieobsługiwane Nieobsługiwane Nieobsługiwane
Func<T1, T2, TResult> Function Nieobsługiwane Nieobsługiwane Nieobsługiwane Nieobsługiwane
Func<T1, T2, T3, TResult> Function Nieobsługiwane Nieobsługiwane Nieobsługiwane Nieobsługiwane

Następujące warunki dotyczą mapowania typów i wartości marshalled:

  • Kolumna Array of wskazuje, czy typ platformy .NET można rozmieścić jako JSArray. Przykład: C# int[] (Int32) zamapowany na JSArray s Number.
  • W przypadku przekazywania JS wartości do języka C# z wartością nieprawidłowego typu struktura zgłasza wyjątek w większości przypadków. Struktura nie wykonuje ewidencjonowania typów w czasie kompilacji.JS
  • JSObjectTask, Exceptioni ArraySegment utwórz GCHandle i serwer proxy. Usunięcie można wyzwolić w kodzie dewelopera lub zezwolić na późniejsze usunięcie obiektów przez program .NET. Te typy mają znaczne obciążenie związane z wydajnością.
  • Array: Przeprowadzanie marshalingu tablicy tworzy kopię tablicy na JS platformie lub .NET.
  • MemoryView
    • MemoryView jest klasą JS środowiska uruchomieniowego .NET WebAssembly do marshalingu Span i ArraySegment.
    • W przeciwieństwie do marshalingu tablicy, marshaling a Span lub ArraySegment nie tworzy kopii pamięci bazowej.
    • MemoryView Można poprawnie utworzyć wystąpienie tylko przez środowisko uruchomieniowe zestawu WebAssembly platformy .NET. W związku z tym nie można zaimportować JS funkcji jako metody .NET, która ma parametr Span lub ArraySegment.
    • MemoryView element utworzony dla elementu Span jest ważny tylko przez czas trwania wywołania międzyoperacyjnego. Ponieważ Span jest przydzielany na stos wywołania wywołania, który nie jest utrwalany po wywołaniu międzyoperamentowym, nie można wyeksportować metody platformy .NET zwracającej Spanelement .
    • MemoryView utworzony dla ArraySegment elementu przetrwa po wywołaniu międzyoperacyjnym i jest przydatny do udostępniania buforu. Wywołanie dispose() elementu utworzonego MemoryView dla ArraySegment serwera proxy powoduje usuwanie serwera proxy i odpina podstawową tablicę .NET. Zalecamy wywołanie dispose() w try-finally bloku dla elementu MemoryView.

W poniższej tabeli przedstawiono obsługiwane mapowania typów.

.NET JavaScript Nullable Task➔doPromise JSMarshalAs Opcjonalne Array of
Boolean Boolean Obsługiwane Obsługiwane Obsługiwane Nieobsługiwane
Byte Number Obsługiwane Obsługiwane Obsługiwane Obsługiwane
Char String Obsługiwane Obsługiwane Obsługiwane Nieobsługiwane
Int16 Number Obsługiwane Obsługiwane Obsługiwane Nieobsługiwane
Int32 Number Obsługiwane Obsługiwane Obsługiwane Obsługiwane
Int64 Number Obsługiwane Obsługiwane Nieobsługiwane Nieobsługiwane
Int64 BigInt Obsługiwane Obsługiwane Nieobsługiwane Nieobsługiwane
Single Number Obsługiwane Obsługiwane Obsługiwane Nieobsługiwane
Double Number Obsługiwane Obsługiwane Obsługiwane Obsługiwane
IntPtr Number Obsługiwane Obsługiwane Obsługiwane Nieobsługiwane
DateTime Date Obsługiwane Obsługiwane Nieobsługiwane Nieobsługiwane
DateTimeOffset Date Obsługiwane Obsługiwane Nieobsługiwane Nieobsługiwane
Exception Error Nieobsługiwane Obsługiwane Obsługiwane Nieobsługiwane
JSObject Object Nieobsługiwane Obsługiwane Obsługiwane Obsługiwane
String String Nieobsługiwane Obsługiwane Obsługiwane Obsługiwane
Object Any Nieobsługiwane Obsługiwane Nieobsługiwane Obsługiwane
Span<Byte> MemoryView Nieobsługiwane Nieobsługiwane Nieobsługiwane Nieobsługiwane
Span<Int32> MemoryView Nieobsługiwane Nieobsługiwane Nieobsługiwane Nieobsługiwane
Span<Double> MemoryView Nieobsługiwane Nieobsługiwane Nieobsługiwane Nieobsługiwane
ArraySegment<Byte> MemoryView Nieobsługiwane Nieobsługiwane Nieobsługiwane Nieobsługiwane
ArraySegment<Int32> MemoryView Nieobsługiwane Nieobsługiwane Nieobsługiwane Nieobsługiwane
ArraySegment<Double> MemoryView Nieobsługiwane Nieobsługiwane Nieobsługiwane Nieobsługiwane
Task Promise Nieobsługiwane Nieobsługiwane Obsługiwane Nieobsługiwane
Action Function Nieobsługiwane Nieobsługiwane Nieobsługiwane Nieobsługiwane
Action<T1> Function Nieobsługiwane Nieobsługiwane Nieobsługiwane Nieobsługiwane
Action<T1, T2> Function Nieobsługiwane Nieobsługiwane Nieobsługiwane Nieobsługiwane
Action<T1, T2, T3> Function Nieobsługiwane Nieobsługiwane Nieobsługiwane Nieobsługiwane
Func<TResult> Function Nieobsługiwane Nieobsługiwane Nieobsługiwane Nieobsługiwane
Func<T1, TResult> Function Nieobsługiwane Nieobsługiwane Nieobsługiwane Nieobsługiwane
Func<T1, T2, TResult> Function Nieobsługiwane Nieobsługiwane Nieobsługiwane Nieobsługiwane
Func<T1, T2, T3, TResult> Function Nieobsługiwane Nieobsługiwane Nieobsługiwane Nieobsługiwane

Następujące warunki dotyczą mapowania typów i wartości marshalled:

  • Kolumna Array of wskazuje, czy typ platformy .NET można rozmieścić jako JSArray. Przykład: C# int[] (Int32) zamapowany na JSArray s Number.
  • W przypadku przekazywania JS wartości do języka C# z wartością nieprawidłowego typu struktura zgłasza wyjątek w większości przypadków. Struktura nie wykonuje ewidencjonowania typów w czasie kompilacji.JS
  • JSObjectTask, Exceptioni ArraySegment utwórz GCHandle i serwer proxy. Usunięcie można wyzwolić w kodzie dewelopera lub zezwolić na późniejsze usunięcie obiektów przez program .NET. Te typy mają znaczne obciążenie związane z wydajnością.
  • Array: Przeprowadzanie marshalingu tablicy tworzy kopię tablicy na JS platformie lub .NET.
  • MemoryView
    • MemoryView jest klasą JS środowiska uruchomieniowego .NET WebAssembly do marshalingu Span i ArraySegment.
    • W przeciwieństwie do marshalingu tablicy, marshaling a Span lub ArraySegment nie tworzy kopii pamięci bazowej.
    • MemoryView Można poprawnie utworzyć wystąpienie tylko przez środowisko uruchomieniowe zestawu WebAssembly platformy .NET. W związku z tym nie można zaimportować JS funkcji jako metody .NET, która ma parametr Span lub ArraySegment.
    • MemoryView element utworzony dla elementu Span jest ważny tylko przez czas trwania wywołania międzyoperacyjnego. Ponieważ Span jest przydzielany na stos wywołania wywołania, który nie jest utrwalany po wywołaniu międzyoperamentowym, nie można wyeksportować metody platformy .NET zwracającej Spanelement .
    • MemoryView utworzony dla ArraySegment elementu przetrwa po wywołaniu międzyoperacyjnym i jest przydatny do udostępniania buforu. Wywołanie dispose() elementu utworzonego MemoryView dla ArraySegment serwera proxy powoduje usuwanie serwera proxy i odpina podstawową tablicę .NET. Zalecamy wywołanie dispose() w try-finally bloku dla elementu MemoryView.

Nazwa modułu w atrybucie [JSImport] i wywołanie, aby załadować moduł w składniku z elementem JSHost.ImportAsync musi być zgodne i być unikatowe w aplikacji. Podczas tworzenia biblioteki do wdrażania w pakiecie NuGet zalecamy używanie przestrzeni nazw pakietów NuGet jako prefiksu w nazwach modułów. W poniższym przykładzie nazwa modułu odzwierciedla Contoso.InteropServices.JavaScript pakiet i folder klas międzyoperacyjności komunikatów użytkownika (UserMessages):

[JSImport("getMessage", 
    "Contoso.InteropServices.JavaScript.UserMessages.CallJavaScript1")]

Funkcje dostępne w globalnej przestrzeni nazw można importować przy użyciu prefiksu globalThis w nazwie funkcji i przy użyciu atrybutu bez podawania nazwy modułu [JSImport] . W poniższym przykładzie console.log element ma prefiks globalThis. Zaimportowana funkcja jest wywoływana przez metodę języka C#, która akceptuje komunikat ciągu języka C# Log (message) i marshalls ciąg języka C# dla JSString elementu :console.log

[JSImport("globalThis.console.log")]
internal static partial void Log([JSMarshalAs<JSType.String>] string message);

Wyeksportuj skrypty ze standardowego modułu JavaScript ES6 ze składnikiem lub umieszczone z innymi statycznymi elementami zawartości JavaScript w JS pliku (na przykład wwwroot/js/{FILE NAME}.js, gdzie JS statyczne zasoby są przechowywane w folderze o nazwie js w folderze aplikacjiwwwroot, a {FILE NAME} symbol zastępczy jest nazwą pliku).

W poniższym przykładzie JS funkcja o nazwie getMessage jest eksportowana ze s collocated JS pliku, który zwraca komunikat powitalny "Hello from Blazor!" w języku portugalskim:

CallJavaScript1.razor.js:

export function getMessage() {
  return 'Olá do Blazor!';
}

Wywoływanie platformy .NET ze środowiska JavaScript

W tej sekcji wyjaśniono, jak wywoływać metody platformy .NET z programu JS.

CallDotNet1 Następujące wywołania JS składnika, które bezpośrednio współdziałają z elementem DOM w celu renderowania ciągu komunikatu powitalnego:

  • Moduł CallDotNetJS jest importowany asynchronicznie ze skomponowanego JS pliku dla tego składnika.
  • Zaimportowana setMessageJS funkcja jest wywoływana przez SetWelcomeMessagefunkcję .
  • Zwrócony komunikat powitalny jest wyświetlany w setMessage interfejsie użytkownika za pośrednictwem message pola .

Ważne

W tym przykładzie JS międzyoperacyjności służy do mutowania elementu DOM wyłącznie w celach demonstracyjnych po renderowaniu składnika w programie OnAfterRender. Zazwyczaj należy mutować JS dom tylko wtedy, gdy obiekt nie wchodzi w interakcję z Blazor. Podejście przedstawione w tej sekcji jest podobne do przypadków, w których biblioteka innej firmy JS jest używana w Razor składniku, w którym składnik wchodzi w interakcję z JS biblioteką za pośrednictwem JS międzyoperacyjności, biblioteka innej firmy JS współdziała z częścią modelu DOM i Blazor nie jest bezpośrednio związana z aktualizacjami MODELU DOM do tej części modelu DOM. Aby uzyskać więcej informacji, zobacz ASP.NET Core Blazor JavaScript interoperability (JS interop).

CallDotNet1.razor:

@page "/call-dotnet-1"
@rendermode InteractiveWebAssembly
@using System.Runtime.InteropServices.JavaScript

<h1>
    JS <code>[JSImport]</code>/<code>[JSExport]</code> Interop 
    (Call .NET Example 1)
</h1>

<p>
    <span id="result">.NET method not executed yet</span>
</p>

@code {
    protected override async Task OnAfterRenderAsync(bool firstRender)
    {
        if (firstRender)
        {
            await JSHost.ImportAsync("CallDotNet1", 
                "../Components/Pages/CallDotNet1.razor.js");

            SetWelcomeMessage();
        }
    }
}
@page "/call-dotnet-1"
@using System.Runtime.InteropServices.JavaScript

<h1>
    JS <code>[JSImport]</code>/<code>[JSExport]</code> Interop 
    (Call .NET Example 1)
</h1>

<p>
    <span id="result">.NET method not executed yet</span>
</p>

@code {
    protected override async Task OnAfterRenderAsync(bool firstRender)
    {
        if (firstRender)
        {
            await JSHost.ImportAsync("CallDotNet1", 
                "../Pages/CallDotNet1.razor.js");

            SetWelcomeMessage();
        }
    }
}

Aby wyeksportować metodę .NET, aby można ją było wywołać z JSklasy , użyj atrybutu[JSExport].

W poniższym przykładzie:

  • SetWelcomeMessageJS wywołuje funkcję o nazwie setMessage. Funkcja JS wywołuje program .NET w celu odebrania komunikatu powitalnego z GetMessageFromDotnet usługi i wyświetli komunikat w interfejsie użytkownika.
  • GetMessageFromDotnet to metoda .NET z [JSExport] atrybutem, który zwraca komunikat powitalny "Hello from Blazor!" w języku portugalskim.

CallDotNet1.razor.cs:

using System.Runtime.InteropServices.JavaScript;
using System.Runtime.Versioning;

namespace BlazorSample.Components.Pages;

[SupportedOSPlatform("browser")]
public partial class CallDotNet1
{
    [JSImport("setMessage", "CallDotNet1")]
    internal static partial void SetWelcomeMessage();

    [JSExport]
    internal static string GetMessageFromDotnet()
    {
        return "Olá do Blazor!";
    }
}

Przestrzeń nazw aplikacji dla poprzedniej klasy częściowej CallDotNet1 to BlazorSample. Przestrzeń nazw składnika to BlazorSample.Components.Pages. Jeśli używasz poprzedniego składnika w lokalnej aplikacji testowej, zaktualizuj przestrzeń nazw aplikacji, aby odpowiadała aplikacji. Na przykład przestrzeń nazw składnika to ContosoApp.Components.Pages , jeśli przestrzeń nazw aplikacji to ContosoApp. Aby uzyskać więcej informacji, zobacz ASP.NET Podstawowe Razor składniki.

W poniższym przykładzie JS funkcja o nazwie setMessage jest importowana ze sprowadzonego JS pliku.

Metoda setMessage:

  • Wywołania globalThis.getDotnetRuntime(0) umożliwiające uwidocznienie wystąpienia środowiska uruchomieniowego platformy .NET zestawu WebAssembly na potrzeby wywoływania wyeksportowanych metod platformy .NET.
  • Uzyskuje eksporty JS zestawu aplikacji. Nazwa zestawu aplikacji w poniższym przykładzie to BlazorSample.
  • Wywołuje metodę BlazorSample.Components.Pages.CallDotNet1.GetMessageFromDotnet z eksportów (exports). Zwrócona wartość, która jest komunikatem powitalnym, jest przypisana <span> do CallDotNet1 tekstu składnika. Przestrzeń nazw aplikacji to BlazorSample, a CallDotNet1 przestrzeń nazw składnika to BlazorSample.Components.Pages.

CallDotNet1.razor.js:

export async function setMessage() {
  const { getAssemblyExports } = await globalThis.getDotnetRuntime(0);
  var exports = await getAssemblyExports("BlazorSample.dll");

  document.getElementById("result").innerText = 
    exports.BlazorSample.Components.Pages.CallDotNet1.GetMessageFromDotnet();
}
using System.Runtime.InteropServices.JavaScript;
using System.Runtime.Versioning;

namespace BlazorSample.Pages;

[SupportedOSPlatform("browser")]
public partial class CallDotNet1
{
    [JSImport("setMessage", "CallDotNet1")]
    internal static partial void SetWelcomeMessage();

    [JSExport]
    internal static string GetMessageFromDotnet()
    {
        return "Olá do Blazor!";
    }
}

Przestrzeń nazw aplikacji dla poprzedniej klasy częściowej CallDotNet1 to BlazorSample. Przestrzeń nazw składnika to BlazorSample.Pages. Jeśli używasz poprzedniego składnika w lokalnej aplikacji testowej, zaktualizuj przestrzeń nazw aplikacji, aby odpowiadała aplikacji. Na przykład przestrzeń nazw składnika to ContosoApp.Pages , jeśli przestrzeń nazw aplikacji to ContosoApp. Aby uzyskać więcej informacji, zobacz ASP.NET Podstawowe Razor składniki.

W poniższym przykładzie JS funkcja o nazwie setMessage jest importowana ze sprowadzonego JS pliku.

Metoda setMessage:

  • Wywołania globalThis.getDotnetRuntime(0) umożliwiające uwidocznienie wystąpienia środowiska uruchomieniowego platformy .NET zestawu WebAssembly na potrzeby wywoływania wyeksportowanych metod platformy .NET.
  • Uzyskuje eksporty JS zestawu aplikacji. Nazwa zestawu aplikacji w poniższym przykładzie to BlazorSample.
  • Wywołuje metodę BlazorSample.Pages.CallDotNet1.GetMessageFromDotnet z eksportów (exports). Zwrócona wartość, która jest komunikatem powitalnym, jest przypisana <span> do CallDotNet1 tekstu składnika. Przestrzeń nazw aplikacji to BlazorSample, a CallDotNet1 przestrzeń nazw składnika to BlazorSample.Pages.

CallDotNet1.razor.js:

export async function setMessage() {
  const { getAssemblyExports } = await globalThis.getDotnetRuntime(0);
  var exports = await getAssemblyExports("BlazorSample.dll");

  document.getElementById("result").innerText = 
    exports.BlazorSample.Pages.CallDotNet1.GetMessageFromDotnet();
}

Uwaga

Wywołanie getAssemblyExports w celu uzyskania eksportów może wystąpić w inicjatorze języka JavaScript w celu zapewnienia dostępności w aplikacji.

Wiele wywołań importu modułu

Po załadowaniu JS modułu funkcje modułu JS są dostępne dla składników i klas aplikacji, o ile aplikacja jest uruchomiona w oknie przeglądarki lub karcie bez ręcznego ponownego załadowania aplikacji przez użytkownika. JSHost.ImportAsync Można wywołać wiele razy w tym samym module bez znacznej kary za wydajność, gdy:

  • Użytkownik odwiedza składnik, który wywołuje JSHost.ImportAsync polecenie importowania modułu, przechodzi z dala od składnika, a następnie wraca do składnika, w którym JSHost.ImportAsync jest wywoływany ponownie w celu zaimportowania tego samego modułu.
  • Ten sam moduł jest używany przez różne składniki i ładowany przez JSHost.ImportAsync poszczególne składniki.

Korzystanie z pojedynczego modułu Języka JavaScript między składnikami

Przed wykonaniem wskazówek w tej sekcji przeczytaj sekcje Wywoływanie języka JavaScript z platformy .NET i wywoływanie platformy .NET z poziomu języka JavaScript w tym artykule, które zawierają ogólne wskazówki dotyczące [JSImport]/[JSExport] międzyoperacji.

W przykładzie w tej sekcji pokazano, jak używać JS międzyoperacji z udostępnionego JS modułu w aplikacji po stronie klienta. Wskazówki zawarte w tej sekcji nie mają zastosowania do Razor bibliotek klas (RCLS).

Używane są następujące składniki, klasy, metody języka C# i JS funkcje:

  • Interop klasa (Interop.cs): konfiguruje importowanie i eksportowanie JS międzyoperajności za pomocą [JSImport] atrybutów i [JSExport] dla modułu o nazwie Interop.
    • GetWelcomeMessage: metoda .NET, która wywołuje zaimportowaną getMessageJS funkcję.
    • SetWelcomeMessage: metoda .NET, która wywołuje zaimportowaną setMessageJS funkcję.
    • GetMessageFromDotnet: Wyeksportowana metoda języka C#, która zwraca ciąg komunikatu powitalnego po wywołaniu z klasy JS.
  • wwwroot/js/interop.js plik: zawiera JS funkcje.
    • getMessage: zwraca komunikat powitalny, gdy jest wywoływany przez kod języka C# w składniku.
    • setMessage: wywołuje metodę GetMessageFromDotnet języka C# i przypisuje zwrócony komunikat powitalny do elementu DOM <span> .
  • Program.cs wywołania JSHost.ImportAsync w celu załadowania modułu z klasy wwwroot/js/interop.js.
  • CallJavaScript2 component (CallJavaScript2.razor): wywołuje GetWelcomeMessage i wyświetla zwrócony komunikat powitalny w interfejsie użytkownika składnika.
  • CallDotNet2 component (CallDotNet2.razor): wywołuje metodę SetWelcomeMessage.

Interop.cs:

using System.Runtime.InteropServices.JavaScript;
using System.Runtime.Versioning;

namespace BlazorSample.JavaScriptInterop;

[SupportedOSPlatform("browser")]
public partial class Interop
{
    [JSImport("getMessage", "Interop")]
    internal static partial string GetWelcomeMessage();

    [JSImport("setMessage", "Interop")]
    internal static partial void SetWelcomeMessage();

    [JSExport]
    internal static string GetMessageFromDotnet()
    {
        return "Olá do Blazor!";
    }
}

W poprzednim przykładzie przestrzeń nazw aplikacji to BlazorSample, a pełną przestrzenią nazw dla klas międzyoperacyjności języka C# jest BlazorSample.JavaScriptInterop.

wwwroot/js/interop.js:

export function getMessage() {
  return 'Olá do Blazor!';
}

export async function setMessage() {
  const { getAssemblyExports } = await globalThis.getDotnetRuntime(0);
  var exports = await getAssemblyExports("BlazorSample.dll");

  document.getElementById("result").innerText =
    exports.BlazorSample.JavaScriptInterop.Interop.GetMessageFromDotnet();
}

System.Runtime.InteropServices.JavaScript Udostępnij przestrzeń nazw w górnej Program.cs części pliku:

using System.Runtime.InteropServices.JavaScript;

Załaduj moduł w przed Program.csWebAssemblyHost.RunAsync wywołaniu:

if (OperatingSystem.IsBrowser())
{
    await JSHost.ImportAsync("Interop", "../js/interop.js");
}

CallJavaScript2.razor:

@page "/call-javascript-2"
@rendermode InteractiveWebAssembly
@using BlazorSample.JavaScriptInterop

<h1>
    JS <code>[JSImport]</code>/<code>[JSExport]</code> Interop 
    (Call JS Example 2)
</h1>

@(message is not null ? message : string.Empty)

@code {
    private string? message;

    protected override void OnInitialized()
    {
        message = Interop.GetWelcomeMessage();
    }
}
@page "/call-javascript-2"
@using BlazorSample.JavaScriptInterop

<h1>
    JS <code>[JSImport]</code>/<code>[JSExport]</code> Interop 
    (Call JS Example 2)
</h1>

@(message is not null ? message : string.Empty)

@code {
    private string? message;

    protected override void OnInitialized()
    {
        message = Interop.GetWelcomeMessage();
    }
}

CallDotNet2.razor:

@page "/call-dotnet-2"
@rendermode InteractiveWebAssembly
@using BlazorSample.JavaScriptInterop

<h1>
    JS <code>[JSImport]</code>/<code>[JSExport]</code> Interop  
    (Call .NET Example 2)
</h1>

<p>
    <span id="result">.NET method not executed</span>
</p>

@code {
    protected override void OnAfterRender(bool firstRender)
    {
        if (firstRender)
        {
            Interop.SetWelcomeMessage();
        }
    }
}
@page "/call-dotnet-2"
@using BlazorSample.JavaScriptInterop

<h1>
    JS <code>[JSImport]</code>/<code>[JSExport]</code> Interop  
    (Call .NET Example 2)
</h1>

<p>
    <span id="result">.NET method not executed</span>
</p>

@code {
    protected override void OnAfterRender(bool firstRender)
    {
        if (firstRender)
        {
            Interop.SetWelcomeMessage();
        }
    }
}

Ważne

W tym przykładzie JS międzyoperacyjności służy do mutowania elementu DOM wyłącznie w celach demonstracyjnych po renderowaniu składnika w programie OnAfterRender. Zazwyczaj należy mutować JS dom tylko wtedy, gdy obiekt nie wchodzi w interakcję z Blazor. Podejście przedstawione w tej sekcji jest podobne do przypadków, w których biblioteka innej firmy JS jest używana w Razor składniku, w którym składnik wchodzi w interakcję z JS biblioteką za pośrednictwem JS międzyoperacyjności, biblioteka innej firmy JS współdziała z częścią modelu DOM i Blazor nie jest bezpośrednio związana z aktualizacjami MODELU DOM do tej części modelu DOM. Aby uzyskać więcej informacji, zobacz ASP.NET Core Blazor JavaScript interoperability (JS interop).

Dodatkowe zasoby