共用方式為


ASP.NET Core Blazor 應用程式中的 JavaScript 位置

注意

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

警告

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

重要

這些發行前產品的相關資訊在產品正式發行前可能會有大幅修改。 Microsoft 對此處提供的資訊,不提供任何明示或暗示的保證。

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

使用下列任何方法載入 JavaScript (JS) 程式碼:

不建議 Blazor 應用程式使用內嵌 JavaScript。 我們建議使用 JS 組合 結合 JS 模組

<script> 標籤的位置

僅在元件保證採用 <script> 並且不需要 .razor的情況下,才會在元件檔案()中放置 標籤。 將 <script> 標籤放在元件檔案中不會產生編譯時期警告或錯誤,但腳本載入行為可能不符合您在採用互動式轉譯模式或具有增強式流覽之靜態 SSR 的元件中的期望。

請勿將 <script> 標籤放在元件檔案 (.razor) 中,因為 <script> 標籤無法動態更新。 將 <script> 標籤放在元件檔中會產生編譯時期錯誤。

注意

文件範例通常會將指令碼放在 <script> 標籤中,或從外部檔案載入全域指令碼。 這些方法會因使用全域函式而污染用戶端。 針對生產應用程式,建議您將 JS 放在個別的 JS模組中,以視需要匯入。 如需詳細資訊,請參閱 JavaScript 模組中的 JavaScript 隔離一節。

注意

文件範例會將指令碼放在 <script> 標籤內,或從外部檔案載入全域指令碼。 這些方法會用全域函式污染用戶端。 ASP.NET Core 5.0 以前的版本不支援將 JS 放在個別的 JS 模組中,以視需要匯入。 如果應用程式需要使用 JS 模組進行 JS 隔離,建議您使用 ASP.NET Core 5.0 或更新版本來建置應用程式。 如需詳細資訊,請使用 [版本] 下拉式清單選取本文的 5.0 或更新版本,並參閱 JavaScript 模組中的 JavaScript 隔離一節。

<head> 標記中載入指令碼

通常不建議使用本節中的方法。

將 JavaScript (JS) 標籤 (<script>...</script>) 放在 <head> 元素標記中:

<head>
    ...

    <script>
      window.jsMethod = (methodParameter) => {
        ...
      };
    </script>
</head>

從 JS 載入 <head> 並不是最佳方法,原因如下:

  • 如果指令碼相依於 JS,則 Blazor Interop 可能會失敗。 建議您使用其中一種其他方法來載入指令碼,而不是透過 <head> 標記載入指令碼。
  • 頁面可能會因為剖析指令碼中的 JS 所需的時間而互動變慢。

在元件標記中,腳本可以透過 HeadContent 元件 載入,但需要注意的是,這種方法會減慢客戶端的頁面載入速度,因此我們建議避免使用。 當腳本在 HeadContent 應用程式、Blazor Server 應用程式或 Blazor WebAssembly 中,透過 Blazor Web App 元件載入,並使用互動式轉譯模組(互動式 SSR、CSR)或具有增強式導覽的靜態 SSR 時,導航離開元件頁面會從已轉譯的 <script> 內容中移除 <head> 標籤,但不會卸載腳本的 JavaScript 代碼,包括腳本註冊的事件處理程式、公開的變數和腳本提供的方法。 只有使用靜態 SSR 且沒有增強導航功能的 Blazor Web App會在使用者離開頁面時卸除 JavaScript 程式代碼。 一般而言,您最好將 <script> 標籤新增至實體 <head> 內容,除非您明確想要在使用這些標籤的元件中保留這類腳本參考,並且不介意程式碼在導覽事件中不被卸載。

在元件標記中,腳本可以透過 HeadContent 元件 載入,但需要注意的是,這種方法會減慢客戶端的頁面載入速度,因此我們建議避免使用。 當腳本以 HeadContent 元件載入時,離開元件的頁面將從轉譯的 <script> 內容中移除 <head> 標籤,但不會卸載腳本的 JavaScript 程式碼,包括腳本註冊的事件處理程式、公開變數,以及腳本提供的方法。 一般而言,您最好將 <script> 標籤新增至實體 <head> 內容,除非您明確想要在使用這些標籤的元件中保留這類腳本參考,並且不介意程式碼在導覽事件中不被卸載。

<body> 標記中載入指令碼

將 JavaScript 標籤 (<script>...</script>) 放在 關閉</body> 元素 內的 Blazor 指令碼參考之後:

<body>
    ...

    <script src="{BLAZOR SCRIPT}"></script>
    <script>
      window.jsMethod = (methodParameter) => {
        ...
      };
    </script>
</body>

在上述範例中,{BLAZOR SCRIPT} 預留位置是 Blazor 指令碼路徑和檔案名稱。 如需指令碼的位置,請參閱 ASP.NET Core Blazor 專案結構

從外部 JavaScript 檔案載入程式碼 (.js) 放置在與元件相同的位置

將 JavaScript (JS) 檔案集合起來用於 Razor 元件,是組織應用程式中指令碼的便利方式。

Razor 應用程式的 Blazor 元件會使用 JS 作為檔案的副檔名來排列 .razor.js 檔案,並可透過專案中檔案的路徑來公開存取:

{PATH}/{COMPONENT}.razor.js

  • {PATH} 預留位置是元件路徑。
  • {COMPONENT} 元件是預留位置。

發佈應用程式時,架構會自動將指令碼移至 Web 根目錄。 指令碼已移至 bin/Release/{TARGET FRAMEWORK MONIKER}/publish/wwwroot/{PATH}/{COMPONENT}.razor.js,其中的佔位符為:

指令碼的相對 URL 不需要變更,因為 Blazor 會為您將 JS 檔案放在已發佈的靜態資產中。

本節和下列範例主要著重於說明 JS 檔案集合。 第一個範例示範共置 JS 檔案與一般 JS 函式。 第二個範例示範如何使用模組來載入函式,這是大部分生產應用程序的建議方法。 從 .NET 呼叫 JS 完全涵蓋於在 ASP.NET Core Blazor 中從 .NET 方法呼叫 JavaScript 函式,其中還以其他範例進一步說明 BlazorJS API。 第二個範例中的元件處置涵蓋於 ASP.NET Core Razor 元件處置中。

下列 JsCollocation1 元件會透過 HeadContent 元件 載入指令碼,並使用 JS 呼叫 IJSRuntime.InvokeAsync 函式。 {PATH} 預留位置是元件路徑。

重要

如果您在測試應用程式中使用下列程式碼進行示範,請將 {PATH} 預留位置變更為元件的路徑 (例如:.NET 8 或更新版本中的 Components/Pages 或 .NET 7 或更早版本中的 Pages)。 在 Blazor Web App (.NET 8 或更新版本) 中,元件需要在應用程式的全域或元件定義上套用互動式渲染模式。

在 Blazor 指令碼後面新增下列指令碼 (Blazor 啟動指令碼的位置):

<script src="{PATH}/JsCollocation1.razor.js"></script>

JsCollocation1 元件 ({PATH}/JsCollocation1.razor):

@page "/js-collocation-1"
@inject IJSRuntime JS

<PageTitle>JS Collocation 1</PageTitle>

<h1>JS Collocation Example 1</h1>

<button @onclick="ShowPrompt">Call showPrompt1</button>

@if (!string.IsNullOrEmpty(result))
{
    <p>
        Hello @result!
    </p>
}

@code {
    private string? result;

    public async Task ShowPrompt()
    {
        result = await JS.InvokeAsync<string>(
            "showPrompt1", "What's your name?");
        StateHasChanged();
    }
}

共置的 JS 檔案會放在 JsCollocation1 元件檔案旁邊,其檔名為 JsCollocation1.razor.js。 在 JsCollocation1 元件中,指令碼會於共置檔案的路徑參考。 在下列範例中,showPrompt1 函式會接受來自 Window prompt() 的使用者名稱,並將它傳回給 JsCollocation1 元件以供顯示。

{PATH}/JsCollocation1.razor.js

function showPrompt1(message) {
  return prompt(message, 'Type your name here');
}

不建議在生產應用程式中普遍使用前述方法,因為此方法會用全域函式污染用戶端。 較適合生產應用程式的方法是使用 JS 模組。 相同的一般準則適用於從共置 JS 檔案載入 JS 模組,如下一個範例所示。

下列 JsCollocation2 元件的 OnAfterRenderAsync 方法會將 JS 模組載入 module 中,這是元件類別的 IJSObjectReferencemodule 用於呼叫 showPrompt2 函式。 {PATH} 是用以指示元件路徑的占位符。

重要

如果您在測試應用程式中使用下列程式碼進行示範,請將 {PATH} 預留位置變更為元件的路徑。 在 Blazor Web App (.NET 8 或更新版本) 中,元件必須全域套用至應用程式或元件定義的互動式渲染模式。

JsCollocation2 元件 ({PATH}/JsCollocation2.razor):

@page "/js-collocation-2"
@implements IAsyncDisposable
@inject IJSRuntime JS

<PageTitle>JS Collocation 2</PageTitle>

<h1>JS Collocation Example 2</h1>

<button @onclick="ShowPrompt">Call showPrompt2</button>

@if (!string.IsNullOrEmpty(result))
{
    <p>
        Hello @result!
    </p>
}

@code {
    private IJSObjectReference? module;
    private string? result;

    protected async override Task OnAfterRenderAsync(bool firstRender)
    {
        if (firstRender)
        {
            /*
                Change the {PATH} placeholder in the next line to the path of
                the collocated JS file in the app. Examples:

                ./Components/Pages/JsCollocation2.razor.js (.NET 8 or later)
                ./Pages/JsCollocation2.razor.js (.NET 7 or earlier)
            */
            module = await JS.InvokeAsync<IJSObjectReference>("import",
                "./{PATH}/JsCollocation2.razor.js");
        }
    }

    public async Task ShowPrompt()
    {
        if (module is not null)
        {
            result = await module.InvokeAsync<string>(
                "showPrompt2", "What's your name?");
            StateHasChanged();
        }
    }

    async ValueTask IAsyncDisposable.DisposeAsync()
    {
        if (module is not null)
        {
            try
            {
                await module.DisposeAsync();
            }
            catch (JSDisconnectedException)
            {
            }
        }
    }
}

在上述範例中,JSDisconnectedException 會在模塊處置期間被截獲,以防 BlazorSignalR 電路中斷。 如果在應用程式中使用Blazor WebAssembly上述程式代碼,則不會SignalR遺失任何連線,因此您可以移除try-catch區塊,並保留處置模組的行 ()。await module.DisposeAsync(); 如需詳細資訊,請參閱 ASP.NET Core Blazor JavaScript 互通性 (JS Interop)

{PATH}/JsCollocation2.razor.js

export function showPrompt2(message) {
  return prompt(message, 'Type your name here');
}

重要

請勿在 Blazor 指令碼 之後放置 <script> 標籤的 JsCollocation2.razor.js ,因為當調用 動態 import() 時,模組會自動加載並快取。

只有當在 Razor 類別庫 (RCL) 中,共置的 JS 使用基於 IJSRuntime 介面的 JS 的 Interop 機制時,才支持指令碼和模組的使用。 如果您要實作 JavaScript [JSImport]/[JSExport] interop,請參閱 JavaScript JSImport/JSExport interop 搭配 ASP.NET CoreBlazor

對於 Razor 類別庫 (RCL) 使用以 IJSRuntime 為基礎的 JS Interop 時提供的指令碼或模組,則會使用下列路徑:

./_content/{PACKAGE ID}/{PATH}/{COMPONENT}.{EXTENSION}.js

  • 需要目前目錄 (./) 的路徑區段,才能建立 JS 檔案的正確靜態資產路徑。
  • {PACKAGE ID} 預留位置是 RCL 的封裝識別碼 (或應用程式所參考類別庫的程式庫名稱)。
  • {PATH} 預留位置是元件路徑。 如果 Razor 元件位於 RCL 的根目錄,則不包含路徑區段。
  • {COMPONENT} 佔位符是元件名稱。
  • {EXTENSION} 預留位置與元件的副檔名相匹配,可以是 razorcshtml

在以下 Blazor 應用程式範例中:

  • RCL 的封裝識別碼為 AppJS
  • 模組的指令碼會針對 JsCollocation3 元件載入 (JsCollocation3.razor)。
  • JsCollocation3 元件位於 RCL 的 Components/Pages 資料夾中。
module = await JS.InvokeAsync<IJSObjectReference>("import", 
    "./_content/AppJS/Components/Pages/JsCollocation3.razor.js");

如需有關 RCL 的詳細資訊,請參閱 從類別庫 (RCL) 取用 ASP.NET Core 元件

從外部 JavaScript 檔案 (.js) 載入指令碼

將具有指令碼來源 (JS) 路徑的 JavaScript (<script>...</script>) 標籤 (src) 放在結尾 </body> 元素內的 Blazor 指令碼參考之後:

<body>
    ...

    <script src="{BLAZOR SCRIPT}"></script>
    <script src="{SCRIPT PATH AND FILE NAME (.js)}"></script>
</body>

對於前面範例中的預留位置:

  • {BLAZOR SCRIPT} 預留位置是 Blazor 指令碼路徑和檔案名稱。 如需指令碼的位置,請參閱 ASP.NET Core Blazor 專案結構
  • {SCRIPT PATH AND FILE NAME (.js)} 預留位置是 wwwroot 下的路徑和指令檔名稱。

在上述 <script> 標籤的下列範例中,scripts.js 檔案位於應用程式的 wwwroot/js 資料夾中:

<script src="js/scripts.js"></script>

如果您不想將所有指令碼保留在 wwwroot 底下的個別資料夾中,也可以直接從 wwwroot 資料夾提供指令碼:

<script src="scripts.js"></script>

當由Razor類別庫提供外部JS檔案時,請使用其穩定的靜態 Web 資產路徑來指定JS檔案:_content/{PACKAGE ID}/{SCRIPT PATH AND FILE NAME (.js)}

  • {PACKAGE ID} 預留位置是程式庫的封裝識別碼。 如果未在專案檔中指定 <PackageId>,則封裝識別碼預設為專案的組件名稱。
  • {SCRIPT PATH AND FILE NAME (.js)} 預留位置是 wwwroot 下的路徑和檔案名稱。
<body>
    ...

    <script src="{BLAZOR SCRIPT}"></script>
    <script src="_content/{PACKAGE ID}/{SCRIPT PATH AND FILE NAME (.js)}"></script>
</body>

在上述 <script> 標籤的下列範例中:

  • Razor 類別庫的組件名稱為 ComponentLibrary,而且未在程式庫的專案檔中指定 <PackageId>
  • scripts.js 檔案位於類別庫的 wwwroot 資料夾中。
<script src="_content/ComponentLibrary/scripts.js"></script>

如需詳細資訊,請參閱從類別庫 (RCL) 取用Razor ASP.NET Core 組件Razor

在 Blazor 啟動前或啟動後插入指令碼

若要確保指令碼在Blazor執行之前或之後載入,請使用 JavaScript 初始化函式。 如需詳細資訊和範例,請參閱 ASP.NET Core Blazor 啟動

在 Blazor 啟動後插入指令碼

若要在 Blazor 啟動後插入指令碼,請鏈結至由手動啟動 Blazor 所產生的 Promise。 如需詳細資訊和範例,請參閱 ASP.NET Core Blazor 啟動

JavaScript 模組中的 JavaScript 隔離

在標準的 模組中啟用 JavaScript () 隔離(ECMAScript 規範)。

JS 隔離提供下列優點:

  • 已匯入的 JS 不再會產生全域命名空間問題。
  • 程式庫和元件的使用者不需要匯入相關的JS。

在伺服器端情境中,務必攔截JSDisconnectedException,以防止因Blazor的SignalR電路損失,導致 Interop 呼叫無法適當處理模組,從而引發未處理的例外狀況。 Blazor WebAssembly應用程式在JS互操作期間不會使用SignalR連線,因此無需在JSDisconnectedException應用程式中設置陷阱來處理Blazor WebAssembly模組的釋放。

如需詳細資訊,請參閱以下資源: