Bagikan melalui


Interop JavaScript [JSImport]/[JSExport] dengan ASP.NET Core Blazor

Catatan

Ini bukan versi terbaru dari artikel ini. Untuk rilis saat ini, lihat versi .NET 8 dari artikel ini.

Penting

Informasi ini berkaitan dengan produk pra-rilis yang mungkin dimodifikasi secara substansial sebelum dirilis secara komersial. Microsoft tidak memberikan jaminan, tersirat maupun tersurat, sehubungan dengan informasi yang diberikan di sini.

Untuk rilis saat ini, lihat versi .NET 8 dari artikel ini.

Artikel ini menjelaskan cara berinteraksi dengan JavaScript (JS) di komponen sisi klien menggunakan API interop JavaScript (JS) [JSImport]/[JSExport] yang dirilis untuk aplikasi yang mengadopsi .NET 7 atau yang lebih baru.

Blazor menyediakan mekanisme interop sendiri JS berdasarkan IJSRuntime antarmuka. BlazorJS Interop didukung secara seragam di seluruh Blazor mode render dan untuk Blazor Hybrid aplikasi. IJSRuntime juga memungkinkan penulis pustaka untuk membangun JS pustaka interop untuk berbagi di seluruh Blazor ekosistem dan tetap menjadi pendekatan yang direkomendasikan untuk JS interop di Blazor. Lihat artikel berikut:

Artikel ini menjelaskan pendekatan interop alternatif JS khusus untuk komponen sisi klien yang dijalankan di WebAssembly. Pendekatan ini sesuai ketika Anda hanya berharap untuk berjalan di WebAssembly sisi klien. Penulis pustaka dapat menggunakan pendekatan ini untuk mengoptimalkan JS interop dengan memeriksa selama eksekusi kode jika aplikasi berjalan di WebAssembly di browser (OperatingSystem.IsBrowser). Pendekatan yang dijelaskan dalam artikel ini harus digunakan untuk menggantiKAN API interop yang tidak terpakai yang usang JS saat bermigrasi ke .NET 7 atau yang lebih baru.

Catatan

Artikel ini berfokus pada JS interop dalam komponen sisi klien. Untuk panduan tentang memanggil .NET di aplikasi JavaScript, lihat Menjalankan .NET dari JavaScript.

API interop JavaScript usang

Interop yang tidak terencana JS menggunakan IJSUnmarshalledRuntime API usang di ASP.NET Core di .NET 7 atau yang lebih baru. Ikuti panduan dalam artikel ini untuk mengganti API usang.

Prasyarat

Unduh dan instal .NET 7 atau yang lebih baru jika belum diinstal pada sistem atau jika sistem belum menginstal versi terbaru.

Ruang nama

JS API interop yang dijelaskan dalam artikel ini dikontrol oleh atribut di System.Runtime.InteropServices.JavaScript namespace layanan.

Aktifkan blok yang tidak aman

AllowUnsafeBlocks Aktifkan properti dalam file proyek aplikasi, yang mengizinkan generator kode di kompilator Roslyn untuk menggunakan pointer untuk JS interop:

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

Peringatan

JS API interop memerlukan pengaktifan AllowUnsafeBlocks. Berhati-hatilah saat menerapkan kode Anda sendiri yang tidak aman di aplikasi .NET, yang dapat menimbulkan risiko keamanan dan stabilitas. Untuk informasi selengkapnya, lihat Kode tidak aman, jenis penunjuk, dan penunjuk fungsi.

Memanggil JavaScript dari .NET

Bagian ini menjelaskan cara memanggil JS fungsi dari .NET.

Dalam komponen CallJavaScript1 berikut:

  • Modul diimpor CallJavaScript1 secara asinkron dari file yang dikolokasi JS dengan JSHost.ImportAsync.
  • Fungsi yang diimpor getMessageJS dipanggil oleh GetWelcomeMessage.
  • String pesan selamat datang yang dikembalikan ditampilkan di UI melalui message bidang .

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

Catatan

Sertakan kode cek masuk bersyarat dengan OperatingSystem.IsBrowser untuk memastikan bahwa JS interop hanya dipanggil oleh komponen yang dirender pada klien. Ini penting untuk pustaka/paket NuGet yang menargetkan komponen sisi server, yang tidak dapat menjalankan kode yang disediakan oleh API interop ini JS .

Untuk mengimpor JS fungsi untuk memanggilnya dari C#, gunakan [JSImport] atribut pada tanda tangan metode C# yang cocok dengan JS tanda tangan fungsi. Parameter pertama untuk [JSImport] atribut adalah nama fungsi yang akan diimpor JS , dan parameter kedua adalah nama JS modul.

Dalam contoh berikut, getMessage adalah JS fungsi yang mengembalikan string untuk modul bernama CallJavaScript1. Tanda tangan metode C#cocok: Tidak ada parameter yang diteruskan ke JS fungsi, dan JS fungsi mengembalikan string. Fungsi JS ini dipanggil oleh GetWelcomeMessage dalam kode 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();
}

Namespace aplikasi untuk kelas parsial sebelumnya CallJavaScript1 adalah BlazorSample. Namespace layanan komponen adalah BlazorSample.Components.Pages. Jika menggunakan komponen sebelumnya di aplikasi pengujian lokal, perbarui namespace agar sesuai dengan aplikasi. Misalnya, namespace layanan adalah ContosoApp.Components.Pages jika namespace aplikasi adalah ContosoApp. Untuk informasi selengkapnya, lihat komponen ASP.NET CoreRazor.

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

Namespace aplikasi untuk kelas parsial sebelumnya CallJavaScript1 adalah BlazorSample. Namespace layanan komponen adalah BlazorSample.Pages. Jika menggunakan komponen sebelumnya di aplikasi pengujian lokal, perbarui namespace agar sesuai dengan aplikasi. Misalnya, namespace layanan adalah ContosoApp.Pages jika namespace aplikasi adalah ContosoApp. Untuk informasi selengkapnya, lihat komponen ASP.NET CoreRazor.

Dalam tanda tangan metode yang diimpor, Anda dapat menggunakan jenis .NET untuk parameter dan mengembalikan nilai, yang dinamai secara otomatis oleh runtime. Gunakan JSMarshalAsAttribute<T> untuk mengontrol bagaimana parameter metode yang diimpor di-marshalled. Misalnya, Anda dapat memilih untuk marshal a long sebagai System.Runtime.InteropServices.JavaScript.JSType.Number atau System.Runtime.InteropServices.JavaScript.JSType.BigInt. Anda dapat meneruskan Action/Func<TResult> panggilan balik sebagai parameter, yang dinamai sebagai fungsi yang dapat JS dipanggil. Anda dapat meneruskan JS referensi objek dan terkelola, dan dinamai sebagai objek proksi, menjaga objek tetap hidup di seluruh batas sampai proksi dikumpulkan sampah. Anda juga dapat mengimpor dan mengekspor metode asinkron dengan Task hasil, yang dinamai sebagai JS janji. Sebagian besar jenis marshalled bekerja di kedua arah, sebagai parameter dan sebagai nilai pengembalian, pada metode yang diimpor dan diekspor, yang tercakup di bagian Panggil .NET dari JavaScript nanti di artikel ini.

Tabel berikut menunjukkan pemetaan jenis yang didukung.

.NET JavaScript Nullable Task➔kePromise JSMarshalAs fakultatif Array of
Boolean Boolean Didukung Didukung Didukung Tidak didukung
Byte Number Didukung Didukung Didukung Didukung
Char String Didukung Didukung Didukung Tidak didukung
Int16 Number Didukung Didukung Didukung Tidak didukung
Int32 Number Didukung Didukung Didukung Didukung
Int64 Number Didukung Didukung Tidak didukung Tidak didukung
Int64 BigInt Didukung Didukung Tidak didukung Tidak didukung
Single Number Didukung Didukung Didukung Tidak didukung
Double Number Didukung Didukung Didukung Didukung
IntPtr Number Didukung Didukung Didukung Tidak didukung
DateTime Date Didukung Didukung Tidak didukung Tidak didukung
DateTimeOffset Date Didukung Didukung Tidak didukung Tidak didukung
Exception Error Tidak didukung Didukung Didukung Tidak didukung
JSObject Object Tidak didukung Didukung Didukung Didukung
String String Tidak didukung Didukung Didukung Didukung
Object Any Tidak didukung Didukung Tidak didukung Didukung
Span<Byte> MemoryView Tidak didukung Tidak didukung Tidak didukung Tidak didukung
Span<Int32> MemoryView Tidak didukung Tidak didukung Tidak didukung Tidak didukung
Span<Double> MemoryView Tidak didukung Tidak didukung Tidak didukung Tidak didukung
ArraySegment<Byte> MemoryView Tidak didukung Tidak didukung Tidak didukung Tidak didukung
ArraySegment<Int32> MemoryView Tidak didukung Tidak didukung Tidak didukung Tidak didukung
ArraySegment<Double> MemoryView Tidak didukung Tidak didukung Tidak didukung Tidak didukung
Task Promise Tidak didukung Tidak didukung Didukung Tidak didukung
Action Function Tidak didukung Tidak didukung Tidak didukung Tidak didukung
Action<T1> Function Tidak didukung Tidak didukung Tidak didukung Tidak didukung
Action<T1, T2> Function Tidak didukung Tidak didukung Tidak didukung Tidak didukung
Action<T1, T2, T3> Function Tidak didukung Tidak didukung Tidak didukung Tidak didukung
Func<TResult> Function Tidak didukung Tidak didukung Tidak didukung Tidak didukung
Func<T1, TResult> Function Tidak didukung Tidak didukung Tidak didukung Tidak didukung
Func<T1, T2, TResult> Function Tidak didukung Tidak didukung Tidak didukung Tidak didukung
Func<T1, T2, T3, TResult> Function Tidak didukung Tidak didukung Tidak didukung Tidak didukung

Kondisi berikut berlaku untuk mengetik nilai pemetaan dan marshalled:

  • Kolom Array of menunjukkan apakah jenis .NET dapat dinamai sebagai JSArray. Contoh: C# int[] (Int32) dipetakan ke JSArray s Number.
  • Saat meneruskan JS nilai ke C# dengan nilai jenis yang salah, kerangka kerja melemparkan pengecualian dalam banyak kasus. Kerangka kerja tidak melakukan pemeriksaan jenis waktu kompilasi di JS.
  • JSObject, Exception, Task dan ArraySegment buat GCHandle dan proksi. Anda dapat memicu pembuangan dalam kode pengembang atau mengizinkan pengumpulan sampah .NET (GC) untuk membuang objek nanti. Jenis-jenis ini membawa overhead performa yang signifikan.
  • Array: Marshaling array membuat salinan array di JS atau .NET.
  • MemoryView
    • MemoryView adalah JS kelas untuk runtime .NET WebAssembly ke marshal Span dan ArraySegment.
    • Tidak seperti marshaling array, marshaling Span atau ArraySegment tidak membuat salinan memori yang mendasar.
    • MemoryView hanya dapat dibuat dengan benar oleh runtime .NET WebAssembly. Oleh karena itu, tidak dimungkinkan untuk mengimpor JS fungsi sebagai metode .NET yang memiliki parameter Span atau ArraySegment.
    • MemoryView dibuat untuk Span hanya valid selama durasi panggilan interop. Seperti Span yang dialokasikan pada tumpukan panggilan, yang tidak bertahan setelah panggilan interop, tidak dimungkinkan untuk mengekspor metode .NET yang mengembalikan Span.
    • MemoryView dibuat untuk ArraySegment bertahan hidup setelah panggilan interop dan berguna untuk berbagi buffer. Memanggil dispose() pada yang MemoryViewArraySegment dibuat untuk membuang proksi dan melepaskan array .NET yang mendasar. Sebaiknya panggil dispose() di try-finally blok untuk MemoryView.

Tabel berikut menunjukkan pemetaan jenis yang didukung.

.NET JavaScript Nullable Task➔kePromise JSMarshalAs fakultatif Array of
Boolean Boolean Didukung Didukung Didukung Tidak didukung
Byte Number Didukung Didukung Didukung Didukung
Char String Didukung Didukung Didukung Tidak didukung
Int16 Number Didukung Didukung Didukung Tidak didukung
Int32 Number Didukung Didukung Didukung Didukung
Int64 Number Didukung Didukung Tidak didukung Tidak didukung
Int64 BigInt Didukung Didukung Tidak didukung Tidak didukung
Single Number Didukung Didukung Didukung Tidak didukung
Double Number Didukung Didukung Didukung Didukung
IntPtr Number Didukung Didukung Didukung Tidak didukung
DateTime Date Didukung Didukung Tidak didukung Tidak didukung
DateTimeOffset Date Didukung Didukung Tidak didukung Tidak didukung
Exception Error Tidak didukung Didukung Didukung Tidak didukung
JSObject Object Tidak didukung Didukung Didukung Didukung
String String Tidak didukung Didukung Didukung Didukung
Object Any Tidak didukung Didukung Tidak didukung Didukung
Span<Byte> MemoryView Tidak didukung Tidak didukung Tidak didukung Tidak didukung
Span<Int32> MemoryView Tidak didukung Tidak didukung Tidak didukung Tidak didukung
Span<Double> MemoryView Tidak didukung Tidak didukung Tidak didukung Tidak didukung
ArraySegment<Byte> MemoryView Tidak didukung Tidak didukung Tidak didukung Tidak didukung
ArraySegment<Int32> MemoryView Tidak didukung Tidak didukung Tidak didukung Tidak didukung
ArraySegment<Double> MemoryView Tidak didukung Tidak didukung Tidak didukung Tidak didukung
Task Promise Tidak didukung Tidak didukung Didukung Tidak didukung
Action Function Tidak didukung Tidak didukung Tidak didukung Tidak didukung
Action<T1> Function Tidak didukung Tidak didukung Tidak didukung Tidak didukung
Action<T1, T2> Function Tidak didukung Tidak didukung Tidak didukung Tidak didukung
Action<T1, T2, T3> Function Tidak didukung Tidak didukung Tidak didukung Tidak didukung
Func<TResult> Function Tidak didukung Tidak didukung Tidak didukung Tidak didukung
Func<T1, TResult> Function Tidak didukung Tidak didukung Tidak didukung Tidak didukung
Func<T1, T2, TResult> Function Tidak didukung Tidak didukung Tidak didukung Tidak didukung
Func<T1, T2, T3, TResult> Function Tidak didukung Tidak didukung Tidak didukung Tidak didukung

Kondisi berikut berlaku untuk mengetik nilai pemetaan dan marshalled:

  • Kolom Array of menunjukkan apakah jenis .NET dapat dinamai sebagai JSArray. Contoh: C# int[] (Int32) dipetakan ke JSArray s Number.
  • Saat meneruskan JS nilai ke C# dengan nilai jenis yang salah, kerangka kerja melemparkan pengecualian dalam banyak kasus. Kerangka kerja tidak melakukan pemeriksaan jenis waktu kompilasi di JS.
  • JSObject, Exception, Task dan ArraySegment buat GCHandle dan proksi. Anda dapat memicu pembuangan dalam kode pengembang atau mengizinkan pengumpulan sampah .NET (GC) untuk membuang objek nanti. Jenis-jenis ini membawa overhead performa yang signifikan.
  • Array: Marshaling array membuat salinan array di JS atau .NET.
  • MemoryView
    • MemoryView adalah JS kelas untuk runtime .NET WebAssembly ke marshal Span dan ArraySegment.
    • Tidak seperti marshaling array, marshaling Span atau ArraySegment tidak membuat salinan memori yang mendasar.
    • MemoryView hanya dapat dibuat dengan benar oleh runtime .NET WebAssembly. Oleh karena itu, tidak dimungkinkan untuk mengimpor JS fungsi sebagai metode .NET yang memiliki parameter Span atau ArraySegment.
    • MemoryView dibuat untuk Span hanya valid selama durasi panggilan interop. Seperti Span yang dialokasikan pada tumpukan panggilan, yang tidak bertahan setelah panggilan interop, tidak dimungkinkan untuk mengekspor metode .NET yang mengembalikan Span.
    • MemoryView dibuat untuk ArraySegment bertahan hidup setelah panggilan interop dan berguna untuk berbagi buffer. Memanggil dispose() pada yang MemoryViewArraySegment dibuat untuk membuang proksi dan melepaskan array .NET yang mendasar. Sebaiknya panggil dispose() di try-finally blok untuk MemoryView.

Nama modul dalam [JSImport] atribut dan panggilan untuk memuat modul dalam komponen harus JSHost.ImportAsync cocok dan unik di aplikasi. Saat menulis pustaka untuk penyebaran dalam paket NuGet, sebaiknya gunakan namespace paket NuGet sebagai awalan dalam nama modul. Dalam contoh berikut, nama modul mencerminkan Contoso.InteropServices.JavaScript paket dan folder kelas interop pesan pengguna (UserMessages):

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

Fungsi yang dapat diakses pada namespace global dapat diimpor dengan menggunakan globalThis awalan dalam nama fungsi dan dengan menggunakan [JSImport] atribut tanpa memberikan nama modul. Dalam contoh berikut, console.log diawali dengan globalThis. Fungsi yang diimpor dipanggil oleh metode C# Log , yang menerima pesan string C# (message) dan marshalls string C# ke JSString untuk console.log:

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

Ekspor skrip dari modul JavaScript ES6 standar baik dikolokasikan dengan komponen atau ditempatkan dengan aset statis JavaScript lainnya dalam JS file (misalnya, wwwroot/js/{FILE NAME}.js, di mana JS aset statis dipertahankan dalam folder bernama js di folder aplikasi wwwroot dan {FILE NAME} tempat penampung adalah nama file).

Dalam contoh berikut, JS fungsi bernama getMessage diekspor dari file yang dikolokasi JS yang mengembalikan pesan selamat datang, "Halo dari Blazor!" dalam bahasa Portugis:

CallJavaScript1.razor.js:

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

Memanggil .NET dari JavaScript

Bagian ini menjelaskan cara memanggil metode .NET dari JS.

Komponen berikut CallDotNet1 memanggil JS yang langsung berinteraksi dengan DOM untuk merender string pesan selamat datang:

  • Modul diimporJSCallDotNet secara asinkron dari file yang dikolokasi JS untuk komponen ini.
  • Fungsi yang diimpor setMessageJS dipanggil oleh SetWelcomeMessage.
  • Pesan selamat datang yang dikembalikan ditampilkan oleh setMessage di UI melalui message bidang .

Penting

Dalam contoh bagian ini, JS interop digunakan untuk memutasi elemen DOM murni untuk tujuan demonstrasi setelah komponen dirender dalam OnAfterRender. Biasanya, Anda hanya boleh membisukan DOM dengan JS ketika objek tidak berinteraksi dengan Blazor. Pendekatan yang ditunjukkan di bagian ini mirip dengan kasus di mana pustaka pihak JS ketiga digunakan dalam Razor komponen, di mana komponen berinteraksi dengan JS pustaka melalui JS interop, pustaka pihak JS ketiga berinteraksi dengan bagian dari DOM, dan Blazor tidak terlibat langsung dengan pembaruan DOM ke bagian DOM tersebut. Untuk informasi selengkapnya, lihat ASP.NET Blazor interoperabilitas Core JavaScript (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();
        }
    }
}

Untuk mengekspor metode .NET sehingga dapat dipanggil dari JS, gunakan [JSExport] atribut .

Dalam contoh berikut:

  • SetWelcomeMessageJS memanggil fungsi bernama setMessage. Fungsi memanggil JS ke .NET untuk menerima pesan selamat datang dari GetMessageFromDotnet dan menampilkan pesan di UI.
  • GetMessageFromDotnet adalah metode .NET dengan [JSExport] atribut yang mengembalikan pesan selamat datang, "Halo dari Blazor!" dalam bahasa Portugis.

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!";
    }
}

Namespace aplikasi untuk kelas parsial sebelumnya CallDotNet1 adalah BlazorSample. Namespace layanan komponen adalah BlazorSample.Components.Pages. Jika menggunakan komponen sebelumnya di aplikasi pengujian lokal, perbarui namespace aplikasi agar sesuai dengan aplikasi. Misalnya, namespace komponen adalah ContosoApp.Components.Pages jika namespace aplikasi adalah ContosoApp. Untuk informasi selengkapnya, lihat komponen ASP.NET CoreRazor.

Dalam contoh berikut, JS fungsi bernama setMessage diimpor dari file yang dikolokasi JS .

Metode setMessage:

  • Panggilan untuk mengekspos instans globalThis.getDotnetRuntime(0) runtime WebAssembly .NET untuk memanggil metode .NET yang diekspor.
  • Mendapatkan ekspor perakitan JS aplikasi. Nama rakitan aplikasi dalam contoh berikut adalah BlazorSample.
  • BlazorSample.Components.Pages.CallDotNet1.GetMessageFromDotnet Memanggil metode dari ekspor (exports). Nilai yang dikembalikan, yang merupakan pesan selamat datang, ditetapkan ke CallDotNet1 teks komponen <span> . Namespace aplikasi adalah BlazorSample, dan CallDotNet1 namespace komponennya adalah 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!";
    }
}

Namespace aplikasi untuk kelas parsial sebelumnya CallDotNet1 adalah BlazorSample. Namespace layanan komponen adalah BlazorSample.Pages. Jika menggunakan komponen sebelumnya di aplikasi pengujian lokal, perbarui namespace aplikasi agar sesuai dengan aplikasi. Misalnya, namespace komponen adalah ContosoApp.Pages jika namespace aplikasi adalah ContosoApp. Untuk informasi selengkapnya, lihat komponen ASP.NET CoreRazor.

Dalam contoh berikut, JS fungsi bernama setMessage diimpor dari file yang dikolokasi JS .

Metode setMessage:

  • Panggilan untuk mengekspos instans globalThis.getDotnetRuntime(0) runtime WebAssembly .NET untuk memanggil metode .NET yang diekspor.
  • Mendapatkan ekspor perakitan JS aplikasi. Nama rakitan aplikasi dalam contoh berikut adalah BlazorSample.
  • BlazorSample.Pages.CallDotNet1.GetMessageFromDotnet Memanggil metode dari ekspor (exports). Nilai yang dikembalikan, yang merupakan pesan selamat datang, ditetapkan ke CallDotNet1 teks komponen <span> . Namespace aplikasi adalah BlazorSample, dan CallDotNet1 namespace komponennya adalah 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();
}

Catatan

Panggilan getAssemblyExports untuk mendapatkan ekspor dapat terjadi di penginisialisasi JavaScript untuk ketersediaan di seluruh aplikasi.

Beberapa panggilan impor modul

JS Setelah modul dimuat, fungsi modul JS tersedia untuk komponen dan kelas aplikasi selama aplikasi berjalan di jendela atau tab browser tanpa pengguna memuat ulang aplikasi secara manual. JSHost.ImportAsync dapat dipanggil beberapa kali pada modul yang sama tanpa penalti performa yang signifikan ketika:

  • Pengguna mengunjungi komponen yang memanggil JSHost.ImportAsync untuk mengimpor modul, menavigasi jauh dari komponen, lalu kembali ke komponen tempat JSHost.ImportAsync dipanggil lagi untuk impor modul yang sama.
  • Modul yang sama digunakan oleh komponen yang berbeda dan dimuat oleh JSHost.ImportAsync di setiap komponen.

Penggunaan modul JavaScript tunggal di seluruh komponen

Sebelum mengikuti panduan di bagian ini, baca bagian Panggil JavaScript dari .NET dan Panggil .NET dari JavaScript di artikel ini, yang memberikan panduan umum tentang [JSImport]/[JSExport] interop.

Contoh di bagian ini menunjukkan cara menggunakan JS interop dari modul bersama JS di aplikasi sisi klien. Panduan di bagian ini tidak berlaku untuk Razor pustaka kelas (RCL).

Komponen, kelas, metode C#, dan JS fungsi berikut digunakan:

  • Interop class (Interop.cs): Menyiapkan interop impor dan ekspor JS dengan [JSImport] atribut dan [JSExport] untuk modul bernama Interop.
    • GetWelcomeMessage: Metode .NET yang memanggil fungsi yang diimpor getMessageJS .
    • SetWelcomeMessage: Metode .NET yang memanggil fungsi yang diimpor setMessageJS .
    • GetMessageFromDotnet: Metode C# yang diekspor yang mengembalikan string pesan selamat datang saat dipanggil dari JS.
  • wwwroot/js/interop.js file: Berisi JS fungsi.
    • getMessage: Mengembalikan pesan selamat datang saat dipanggil oleh kode C# dalam komponen.
    • setMessage: Memanggil GetMessageFromDotnet metode C# dan menetapkan pesan selamat datang yang dikembalikan ke elemen DOM <span> .
  • Program.csJSHost.ImportAsync panggilan untuk memuat modul dari wwwroot/js/interop.js.
  • CallJavaScript2 komponen (CallJavaScript2.razor): Memanggil GetWelcomeMessage dan menampilkan pesan selamat datang yang dikembalikan di UI komponen.
  • CallDotNet2 komponen (CallDotNet2.razor): Memanggil 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!";
    }
}

Dalam contoh sebelumnya, namespace aplikasi adalah BlazorSample, dan namespace lengkap untuk kelas interop C# adalah 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();
}

Jadikan System.Runtime.InteropServices.JavaScript namespace tersedia di bagian Program.cs atas file:

using System.Runtime.InteropServices.JavaScript;

Muat modul sebelumnya Program.csWebAssemblyHost.RunAsync dipanggil:

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

Penting

Dalam contoh bagian ini, JS interop digunakan untuk memutasi elemen DOM murni untuk tujuan demonstrasi setelah komponen dirender dalam OnAfterRender. Biasanya, Anda hanya boleh membisukan DOM dengan JS ketika objek tidak berinteraksi dengan Blazor. Pendekatan yang ditunjukkan di bagian ini mirip dengan kasus di mana pustaka pihak JS ketiga digunakan dalam Razor komponen, di mana komponen berinteraksi dengan JS pustaka melalui JS interop, pustaka pihak JS ketiga berinteraksi dengan bagian dari DOM, dan Blazor tidak terlibat langsung dengan pembaruan DOM ke bagian DOM tersebut. Untuk informasi selengkapnya, lihat ASP.NET Blazor interoperabilitas Core JavaScript (JS interop).

Sumber Daya Tambahan: