共用方式為


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

注意

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

警告

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

重要

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

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

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

警告

只有在元件保證採用靜態伺服器端轉譯 (靜態 SSR) 時,才會將 <script> 標籤放在元件檔案 (.razor) 中,因為 <script> 標籤無法動態更新。

警告

請勿將 <script> 標籤放在元件檔案 (.razor) 中,因為 <script> 標籤無法動態更新。

注意

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

注意

文件範例會將指令碼放在 <script> 標籤內,或從外部檔案載入全域指令碼。 這些方法會利用全域函式來使用戶端產生問題。 在 ASP.NET Core 5.0 以前的 Blazor支援將 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>

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

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

<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 元件,是組織應用程式中指令碼的便利方式。

Blazor 應用程式的 Razor 元件會使用 .razor.js 副檔名來共置 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 元件 載入指令碼,並使用 IJSRuntime.InvokeAsync 呼叫 JS 函式。 {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 void 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 void 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遺失任何連線,因此您可以移除-catch try區塊,並保留處置模組的行 ()。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 的 JS Interop 機制以 IJSRuntime 介面為基礎時,才支援對 Razor 類別庫 (RCL) 中共置的 JS 使用指令碼和模組。 如果您要實作 JavaScript [JSImport]/[JSExport] interop,請參閱 JavaScript Import/Export interop 搭配 ASP.NET Core Blazor

對於 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 的詳細資訊,請參閱從 Razor 類別庫 (RCL) 取用 ASP.NET Core Razor

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

將具有指令碼來源 (src) 路徑的 JavaScript (JS) 標籤 (<script>...</script>) 放在結尾 </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>

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

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

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

在 Blazor 啟動後插入指令碼

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

JavaScript 模組中的 JavaScript 隔離

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

JS 隔離提供下列優點:

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

在伺服器端案例中,當線路遺失BlazorSignalR時,JS一律會設陷JSDisconnectedException,以防止 Interop 呼叫處置模組,這會導致未處理的例外狀況。 Blazor WebAssemblyapp 不會在 Interop 期間JS使用SignalR連線,因此不需要在Blazor WebAssembly應用程式中設陷JSDisconnectedException模塊處置。

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