共用方式為


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

注意

這不是這篇文章的最新版本。 如需目前版本,請參閱本文的 .NET 8 版本

警告

不再支援此版本的 ASP.NET Core。 如需詳細資訊,請參閱 .NET 和 .NET Core 支援原則。 如需目前版本,請參閱本文的 .NET 8 版本

重要

這些發行前產品的相關資訊在產品正式發行前可能會有大幅修改。 Microsoft 對此處提供的資訊,不做任何明確或隱含的瑕疵擔保。

如需目前版本,請參閱本文的 .NET 8 版本

本文說明如何使用 JavaScript (JS) [JSImport]/[JSExport] Interop API,與用戶端元件中的 JavaScript (JS) 互動。 如需其他資訊與範例,請參閱 在 .NET WebAssembly 中的 JavaScript `[JSImport]`/`[JSExport]` 互通

如需其他指引,請參閱 .NET 執行階段 (dotnet/runtime) GitHub 存放庫中的設定和裝載 .NET WebAssembly 應用程式指引。

Blazor 會根據 IJSRuntime 介面提供自己的 JS Interop 機制。 Blazor 跨轉譯模式和 Blazor Hybrid 應用程式都一致支援 Blazor 的 JS Interop。 IJSRuntime 也可讓程式庫作者建置可跨 Blazor 生態系統共用的 JS Interop 程式庫,並且仍然是 Blazor 中 JS Interop 的建議方法。 請參閱以下文章:

本文描述在 WebAssembly 上執行的用戶端元件特定的替代 JS Interop 方法。 當您只預期在用戶端 WebAssembly 上執行時,這些方法就很合適。 程式庫作者可以使用這些方法來最佳化 JS Interop,方法是在程式碼執行期間檢查應用程式是否在瀏覽器 (OperatingSystem.IsBrowser) 中的 WebAssembly 上執行。 本文所述的方法應該用來在移轉至 .NET 7 或更新版本時取代過時的解除封送 JS Interop API。

注意

本文著重於用戶端元件中的 JS Interop。 如需在 JavaScript 應用程式中呼叫 .NET 的指引,請參閱 JavaScript `[JSImport]`/`[JSExport]` 與 WebAssembly 瀏覽器應用程式專案互通

過時的 JavaScript Interop API

使用 IJSUnmarshalledRuntime API 解除封送的 JS Interop 在 .NET 7 或更新版本的 ASP.NET Core 中已淘汰。 遵循本文中的指導來取代過時的 API。

必要條件

Visual Studio 搭配 ASP.NET 與網頁程式開發工作負載。

如果您規劃要在從 Blazor WebAssembly 專案範本產生的 Blazor WebAssembly 應用程式中實作 [JSImport]/[JSExport] Interop,就不需要進一步的工具。

如果您規劃要使用 WebAssembly Browser 或 WebAssembly Console App 專案範本,請使用下列命令安裝 Microsoft.NET.Runtime.WebAssembly.Templates NuGet 套件:

dotnet new install Microsoft.NET.Runtime.WebAssembly.Templates

如需詳細資訊,請參閱 JavaScript `[JSImport]`/`[JSExport]` 與 WebAssembly 瀏覽器應用程式專案互通

Namespace

本文所述的 JS Interop API (JSHost.ImportAsync) 是由 System.Runtime.InteropServices.JavaScript 命名空間中的屬性所控制。

啟用不安全的區塊

啟用應用程式專案檔中的 AllowUnsafeBlocks 屬性,其會允許 Roslyn 編譯器中的程式碼產生器使用指標進行 JS Interop:

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

警告

JS Interop API 需要啟用 AllowUnsafeBlocks。 在 .NET 應用程式中實作本身不安全的程式碼時請小心,這可能會帶來安全性和穩定性風險。 如需詳細資訊,請參閱不安全的程式碼、指標型別和函式指標

不支援 Razor 類別庫 (RCL) 共置的 JS

一般而言,對於以 IJSRuntime 為基礎的 JS Interop,其 JS 位置支援 (ASP.NET Core Blazor 應用程式中的 JavaScript 位置) 也會為本文中描述的 [JSImport]/[JSExport] 顯示。 唯一不支援的 JS 位置功能是用於 Razor 類別庫 (RCL) 中共置的 JS 時

請不要在 RCL 中使用共置的 JS,而是將 JS 檔案放在 RCL 的 wwwroot 資料夾中,並使用 RCL 靜態資產的一般路徑加以參考:

_content/{PACKAGE ID}/{PATH}/{FILE NAME}.js

  • {PACKAGE ID} 預留位置是 RCL 的封裝識別碼 (或類別庫的庫名)。
  • {PATH} 預留位置是檔案的路徑。
  • {FILE NAME} 預留位置是檔案名稱。

[JSImport]/[JSExport] Interop 不支援 RCL 中共置的 JS,但您可以採用下列其中一種方法或兩種方法來使您的 JS 檔案井然有序:

  • 將 JS 檔案命名為使用 JS 的元件名稱。 針對名為 CallJavaScriptFromLib (CallJavaScriptFromLib.razor) 之 RCL 中的元件,命名 wwwroot 資料夾中的 CallJavaScriptFromLib.js 檔案。
  • 將元件專屬的 JS 檔案放在 RCL wwwroot 資料夾內的 Components 資料夾中,並在檔案的路徑中使用 "Components":_content/{PACKAGE ID}/Components/CallJavaScriptFromLib.js

從 .NET 呼叫 JavaScript

本節說明如何從 .NET 呼叫 JS 函式。

在下列 CallJavaScript1 元件中:

  • CallJavaScript1 模組會以非同步方式從共置的 JS 檔案使用 JSHost.ImportAsync 匯入。
  • 匯入的 getMessageJS 函式是由 GetWelcomeMessage 呼叫。
  • 傳回的歡迎訊息字串會透過 message 欄位顯示在 UI 中。

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

注意

使用 OperatingSystem.IsBrowser 在程式碼中包含條件式簽入,以確保 JS Interop 只會由用戶端上轉譯的元件呼叫。 對於以伺服器端元件為目標的程式庫/NuGet 封裝 (其無法執行此 JS Interop API 所提供的程式碼),這很重要。

若要匯入 JS 函式以從 C# 呼叫它,請在符合 JS 函式簽章的 C# 方法簽章上使用 [JSImport] 屬性[JSImport] 屬性的第一個參數是要匯入 JS 函式的名稱,而第二個參數是 JS 模組的名稱。

在下列範例中,getMessage 是針對名為 CallJavaScript1 的模組傳回 string 的 JS 函式。 C# 方法簽章相符:不會將任何參數傳遞至 JS 函式,而 JS 函式會傳回 string。 JS 函式是由 GetWelcomeMessage 在 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();
}

上述 CallJavaScript1 部分類別的應用程式命名空間為 BlazorSample。 元件的命名空間為 BlazorSample.Components.Pages。 如果在本機測試應用程式中使用上述元件,請更新命名空間以符合應用程式。 例如,如果應用程式的命名空間是 ContosoApp,則命名空間為 ContosoApp.Components.Pages。 如需詳細資訊,請參閱 ASP.NET Core Razor 元件

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

上述 CallJavaScript1 部分類別的應用程式命名空間為 BlazorSample。 元件的命名空間為 BlazorSample.Pages。 如果在本機測試應用程式中使用上述元件,請更新命名空間以符合應用程式。 例如,如果應用程式的命名空間是 ContosoApp,則命名空間為 ContosoApp.Pages。 如需詳細資訊,請參閱 ASP.NET Core Razor 元件

在匯入的方法簽章中,您可以使用 .NET 型別作為參數和傳回值,其會由執行階段自動封送處理。 使用 JSMarshalAsAttribute<T> 來控制匯入的方法參數如何封送處理。 例如,您可以選擇將 long 封送處理為 System.Runtime.InteropServices.JavaScript.JSType.NumberSystem.Runtime.InteropServices.JavaScript.JSType.BigInt。 您可以將 Action/Func<TResult> 回呼作為參數傳遞,這些回呼會封送為可呼叫的 JS 函式。 您可以傳遞 JS 和受控物件參考,而且它們會封送處理為 Proxy 物件,讓物件在跨邊界保持運作,直到 Proxy 被垃圾回收為止。 您也可以使用 Task 結果匯入和匯出非同步方法,這些方法會按照 JS Promises 進行封送處理。 大部分封送處理型別可以以參數和傳回值形式,在匯入和匯出方法上雙向運作,本文稍後的從 JavaScript 呼叫 .NET 小節將會說明。

如需其他類型對應資訊與範例,請參閱 .NET WebAssembly 中的 JavaScript `[JSImport]`/`[JSExport]` 互通

[JSImport] 屬性中的模組名稱,以及使用 JSHost.ImportAsync 在元件中載入模組的呼叫必須相符且在應用程式中是唯一的。 撰寫程式庫以在 NuGet 封裝中部署時,建議您使用 NuGet 封裝命名空間作為模組名稱的前置詞。 在下列範例中,模組名稱會反映 Contoso.InteropServices.JavaScript 封裝和使用者訊息 Interop 類別的資料夾 (UserMessages):

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

可在全域命名空間上存取的函式,可以在函式名稱中使用 globalThis 前置詞,以及使用 [JSImport] 屬性而不提供模組名稱來匯入。 在下列範例中,console.log 的前置詞為 globalThis。 匯入的函式是由 C# Log 方法呼叫,該方法接受 C# 字串訊息(message) 並將 C# 字串封送處理為console.log 的 JSString

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

從標準 JavaScript 模組匯出指令碼,以與元件共置,或與其他 JavaScript 靜態資產放置在 JS 檔案中 (例如,wwwroot/js/{FILE NAME}.js,其中的 JS 靜態資產會保留在應用程式 wwwroot 資料夾中名為 js 的資料夾中,而 {FILE NAME} 預留位置是檔案名稱)。

在下列範例中,名為 getMessage 的 JS 函式會從共置的 JS 檔案匯出,其會傳回葡萄牙文的歡迎訊息 "Hello from Blazor!":

CallJavaScript1.razor.js

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

從 JavaScript 呼叫 .NET

本節說明如何從 JS 呼叫 .NET 方法。

下列 CallDotNet1 元件會呼叫直接與 DOM 互動以轉譯歡迎訊息字串的 JS:

  • CallDotNet JS 模組會從此元件的共置 JS 檔案非同步匯入。
  • 匯入的 setMessageJS 函式是由 SetWelcomeMessage 呼叫。
  • 傳回的歡迎訊息字串會由 setMessage 透過 message 欄位顯示在 UI 中。

重要

在本節的範例中,JS Interop 是用來在 OnAfterRender 中轉譯元件之後,純粹為了示範目的而變動 DOM 元素。 一般而言,您只應該在物件未與 Blazor 互動時使用 JS 來變動 DOM。 本節中顯示的方法與 Razor 元件中使用的第三方 JS 程式庫的情況類似,其中元件會透過 JS Interop 與 JS 程式庫互動,第三方 JS 程式庫會與 DOM 的一部分互動,而 Blazor 不會直接與對 DOM 部分的 DOM 更新相關。 如需詳細資訊,請參閱 ASP.NET Core Blazor 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();
        }
    }
}

若要匯出 .NET 方法,以便從 JS 呼叫它,請使用 [JSExport] 屬性

在以下範例中:

  • SetWelcomeMessage 會呼叫名為 setMessage 的 JS 函式。 JS 函式會呼叫 .NET,以接收來自 GetMessageFromDotnet 的歡迎訊息,並在 UI 中顯示訊息。
  • GetMessageFromDotnet 是 .NET 方法,其 [JSExport] 屬性會以葡萄牙文傳回歡迎訊息 "Hello from Blazor!"。

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() => "Olá do Blazor!";
}

上述 CallDotNet1 部分類別的應用程式命名空間為 BlazorSample。 元件的命名空間為 BlazorSample.Components.Pages。 如果在本機測試應用程式中使用上述元件,請更新應用程式命名空間以符合應用程式。 例如,如果應用程式的命名空間是 ContosoApp,則元件命名空間為 ContosoApp.Components.Pages。 如需詳細資訊,請參閱 ASP.NET Core Razor 元件

在下列範例中,名為 setMessage 的 JS 函式會從共置的 JS 檔案匯入。

setMessage 方法:

  • 呼叫 globalThis.getDotnetRuntime(0) 以公開 WebAssembly .NET 執行階段執行個體,以呼叫匯出的 .NET 方法。
  • 取得應用程式元件的 JS 匯出。 下列範例中應用程式元件的名稱為 BlazorSample
  • 從匯出 (exports) 呼叫 BlazorSample.Components.Pages.CallDotNet1.GetMessageFromDotnet 方法。 傳回的值,即歡迎訊息,會指派給 CallDotNet1 元件的 <span> 文字。 應用程式的命名空間為 BlazorSample,而 CallDotNet1 元件的命名空間為 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() => "Olá do Blazor!";
}

上述 CallDotNet1 部分類別的應用程式命名空間為 BlazorSample。 元件的命名空間為 BlazorSample.Pages。 如果在本機測試應用程式中使用上述元件,請更新應用程式命名空間以符合應用程式。 例如,如果應用程式的命名空間是 ContosoApp,則元件命名空間為 ContosoApp.Pages。 如需詳細資訊,請參閱 ASP.NET Core Razor 元件

在下列範例中,名為 setMessage 的 JS 函式會從共置的 JS 檔案匯入。

setMessage 方法:

  • 呼叫 globalThis.getDotnetRuntime(0) 以公開 WebAssembly .NET 執行階段執行個體,以呼叫匯出的 .NET 方法。
  • 取得應用程式元件的 JS 匯出。 下列範例中應用程式元件的名稱為 BlazorSample
  • 從匯出 (exports) 呼叫 BlazorSample.Pages.CallDotNet1.GetMessageFromDotnet 方法。 傳回的值,即歡迎訊息,會指派給 CallDotNet1 元件的 <span> 文字。 應用程式的命名空間為 BlazorSample,而 CallDotNet1 元件的命名空間為 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();
}

注意

呼叫 getAssemblyExports 以取得匯出可能發生在 JavaScript 初始化運算式中,以取得整個應用程式的可用性。

多個模組匯入呼叫

載入 JS 模組之後,只要應用程式在瀏覽器視窗或索引標籤中執行,模組的 JS 函式就可供應用程式的元件和類別使用,而不需要使用者手動重新載入應用程式。 JSHost.ImportAsync 可以在相同的模組上呼叫多次,而不會在下列情況下大幅降低效能:

  • 使用者會瀏覽呼叫 JSHost.ImportAsync 以匯入模組的元件、導覽離開元件,然後返回元件,在其中會再次呼叫 JSHost.ImportAsync 以取得相同模組匯入。
  • 相同模組會由不同的元件使用,並由 JSHost.ImportAsync 在每個元件中載入。

跨元件使用單一 JavaScript 模組

遵循本節中的指導之前,請閱讀本文的從 .NET 呼叫 JavaScript從 JavaScript 呼叫 .NET 小節,其中提供有關 [JSImport]/[JSExport] Interop 的一般指導。

本節中的範例示範如何從用戶端應用程式中的共用 JS 模組使用 JS Interop。 本節中的指導不適用 Razor 類別庫 (RCL)。

使用下列元件、類別、C# 方法和 JS 函式:

  • Interop 類別 (Interop.cs):使用名為 Interop 的模組的 [JSImport][JSExport] 屬性,設定匯入和匯出 JS Interop。
    • GetWelcomeMessage:呼叫匯入的 getMessageJS 函式的 .NET 方法。
    • SetWelcomeMessage:呼叫匯入的 setMessageJS 函式的 .NET 方法。
    • GetMessageFromDotnet:匯出的 C# 方法,會在從 JS 呼叫時傳回歡迎訊息字串。
  • wwwroot/js/interop.js 檔案:包含 JS 函式。
    • getMessage:在元件中由 C# 程式碼呼叫時傳回歡迎訊息。
    • setMessage:呼叫 GetMessageFromDotnet C# 方法,並將傳回的歡迎訊息指派給 DOM <span> 元素。
  • Program.cs 呼叫 JSHost.ImportAsync 以從 wwwroot/js/interop.js 載入模組。
  • CallJavaScript2 元件 (CallJavaScript2.razor):在元件的 UI 中呼叫 GetWelcomeMessage 並顯示傳回的歡迎訊息。
  • CallDotNet2 元件 (CallDotNet2.razor):呼叫 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() => "Olá do Blazor!";
}

在上述範例中,應用程式的命名空間是 BlazorSample,而 C# Interop 類別的完整命名空間為 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 命名空間在 Program.cs 檔案頂端提供:

using System.Runtime.InteropServices.JavaScript;

在呼叫 WebAssemblyHost.RunAsync 之前在 Program.cs 中載入模組:

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

重要

在本節的範例中,JS Interop 是用來在 OnAfterRender 中轉譯元件之後,純粹為了示範目的而變動 DOM 元素。 一般而言,您只應該在物件未與 Blazor 互動時使用 JS 來變動 DOM。 本節中顯示的方法與 Razor 元件中使用的第三方 JS 程式庫的情況類似,其中元件會透過 JS Interop 與 JS 程式庫互動,第三方 JS 程式庫會與 DOM 的一部分互動,而 Blazor 不會直接與對 DOM 部分的 DOM 更新相關。 如需詳細資訊,請參閱 ASP.NET Core Blazor JavaScript 互通性 (JS Interop)

其他資源