備註
這不是本文的最新版本。 關於目前版本,請參閱 本文的 .NET 10 版本。
警告
此版本的 ASP.NET Core 已不再受支援。 如需詳細資訊,請參閱 .NET 和 .NET Core 支援政策。 關於目前版本,請參閱 本文的 .NET 10 版本。
本文說明如何在Blazor中觸發及處理頁面導覽。 使用者可透過一般 HTML 連結在不同頁面間移動,但 Blazor 應用程式內的導航功能提升,避免整頁重新載入,並提供更流暢的體驗。 使用元件 NavLink 建立導覽連結,當連結與當前頁面匹配時,會自動套用樣式。 若要進行程式化導航與 C# 程式碼中的 URI 管理,請使用該 NavigationManager 服務。
本文說明如何在Blazor中觸發及處理頁面導覽。 使用元件 NavLink 建立導覽連結,當連結與當前頁面匹配時,會自動套用樣式。 若要進行程式化導航與 C# 程式碼中的 URI 管理,請使用該 NavigationManager 服務。
這很重要
本文中的程式碼範例會顯示在 Navigation 上呼叫的方法,其為在類別和元件中插入的 NavigationManager。
NavLink 元件
建立導覽連結時,請使用 NavLink 元件以取代 HTML 超連結元素 (<a>)。
NavLink 元件的行為與 <a> 元素類似,不同之處在於它會根據其 active 是否符合目前的 URL 來切換 href CSS 類別。
active 類別可協助使用者了解哪個頁面是顯示的導覽連結中的作用中頁面。 選擇性地將 CSS 類別名稱指派給 NavLink.ActiveClass,以在目前的路由符合 href 時,將自訂 CSS 類別套用至轉譯的連結。
在從Blazor專案範本建立的Blazor應用程式中,NavMenu元件(NavMenu.razor):
<div class="nav-item px-3">
<NavLink class="nav-link" href="" Match="NavLinkMatch.All">
<span class="bi bi-house-door-fill-nav-menu" aria-hidden="true"></span> Home
</NavLink>
</div>
<div class="nav-item px-3">
<NavLink class="nav-link" href="counter">
<span class="bi bi-plus-square-fill-nav-menu" aria-hidden="true"></span> Counter
</NavLink>
</div>
在上述範例中,HomeNavLinkhref="" 符合主 URL,而且只會在應用程式的預設基底路徑 (active) 接收 / CSS 類別。 第二個NavLink當使用者造訪Counter元件時,會獲得/counter類別active。
有兩個選項可指派給 NavLinkMatch 元素的 Match 屬性:
-
NavLinkMatch.All:NavLink 當與當前的 URL 相符時為啟用狀態,但忽略查詢字串和片段。 若要在查詢字串或片段中進行比對,請將
Microsoft.AspNetCore.Components.Routing.NavLink.EnableMatchAllForQueryStringAndFragmentAppContext的參數設為true。 - NavLinkMatch.Prefix (預設值):當 NavLink 符合目前 URL 的任何前置詞時,它會作用中。
若要採用自定義匹配邏輯,您需要將 NavLink 子類化並覆寫它的 ShouldMatch 方法。 當您要套用 true CSS 類別時,請從 方法傳回 active:
public class CustomNavLink : NavLink
{
protected override bool ShouldMatch(string currentUriAbsolute)
{
// Custom matching logic
}
}
有兩個選項可指派給 NavLinkMatch 元素的 Match 屬性:
- NavLinkMatch.All:當 NavLink 與整個目前的URL匹配時,即為活躍狀態,包含查詢字串和片段。
- NavLinkMatch.Prefix (預設值):當 NavLink 符合目前 URL 的任何前置詞時,它會作用中。
其他 NavLink 元件屬性會傳遞至轉譯的錨標籤。 在下列範例中,NavLink 元件包含 target 屬性:
<NavLink href="example-page" target="_blank">Example page</NavLink>
將會轉譯以下 HTML 標記:
<a href="example-page" target="_blank">Example page</a>
警告
由於 Blazor 轉譯子內容的方式,如果在 NavLink (子) 元件的內容中使用遞增迴圈變數,則在 for 迴圈內轉譯 NavLink 元件需要用到本機索引變數:
@for (int c = 1; c < 4; c++)
{
var ct = c;
<li ...>
<NavLink ...>
<span ...></span> Product #@ct
</NavLink>
</li>
}
在此案例中使用索引變數是在其子內容中使用迴圈變數的任何子元件的需求,而不只是 NavLink 元件。
或者,使用foreach的迴圈來搭配Enumerable.Range:
@foreach (var c in Enumerable.Range(1, 3))
{
<li ...>
<NavLink ...>
<span ...></span> Product #@c
</NavLink>
</li>
}
URI 與導航狀態輔助工具
使用 NavigationManager 來管理 C# 程式碼中的 URI 和導覽。 NavigationManager 提供下表所示的事件和方法。
| 會員 | Description |
|---|---|
| Uri | 取得目前的絕對 URI。 |
| BaseUri | 取得具有尾端斜線的基底 URI,該 URI 可加在相對 URI 路徑前面,以便生成絕對 URI。 一般而言,BaseUri 會對應至文件 href 元素上的 <base> 屬性 (<head> 內容的位置)。 |
| NavigateTo | 導覽至指定的 URI。 如果 forceLoad 為 false:
forceLoad 為 true:
如需詳細資訊,請參閱增強式導覽和表單處理一節。 如果 |
| LocationChanged | 當導航位置發生變更時觸發的事件。 如需詳細資訊,請參閱位置變更一節。 |
NotFound |
呼叫 以處理找不到要求資源的案例。 如需詳細資訊,請參閱 找不到回應 一節。 |
| ToAbsoluteUri | 將相對 URI 轉換成絕對 URI。 |
| ToBaseRelativePath | 根據應用程式的基底 URI,將絕對 URI 轉換成相對於基底 URI 前置詞的 URI。 如需範例,請參閱產生相對於基底 URI 前置詞的 URI 一節。 |
RegisterLocationChangingHandler |
註冊一個事件處理器來處理進入的導覽事件。 呼叫 NavigateTo 總是會叫用處理常式。 |
| GetUriWithQueryParameter | 傳回更新 NavigationManager.Uri 而建構的 URI,並新增、更新或移除單一參數。 如需詳細資訊,請參閱查詢字串一節。 |
| 會員 | Description |
|---|---|
| Uri | 取得目前的絕對 URI。 |
| BaseUri | 取得具有尾端斜線的基底 URI,該 URI 可加在相對 URI 路徑前面,以便生成絕對 URI。 一般而言,BaseUri 會對應至文件 href 元素上的 <base> 屬性 (<head> 內容的位置)。 |
| NavigateTo | 導覽至指定的 URI。 如果 forceLoad 為 false:
forceLoad 為 true:
如需詳細資訊,請參閱增強式導覽和表單處理一節。 如果 |
| LocationChanged | 當導航位置發生變更時觸發的事件。 如需詳細資訊,請參閱位置變更一節。 |
| ToAbsoluteUri | 將相對 URI 轉換成絕對 URI。 |
| ToBaseRelativePath | 根據應用程式的基底 URI,將絕對 URI 轉換成相對於基底 URI 前置詞的 URI。 如需範例,請參閱產生相對於基底 URI 前置詞的 URI 一節。 |
RegisterLocationChangingHandler |
註冊一個事件處理器來處理進入的導覽事件。 呼叫 NavigateTo 總是會叫用處理常式。 |
| GetUriWithQueryParameter | 傳回更新 NavigationManager.Uri 而建構的 URI,並新增、更新或移除單一參數。 如需詳細資訊,請參閱查詢字串一節。 |
| 會員 | Description |
|---|---|
| Uri | 取得目前的絕對 URI。 |
| BaseUri | 取得具有尾端斜線的基底 URI,該 URI 可加在相對 URI 路徑前面,以便生成絕對 URI。 一般而言,BaseUri 會對應至文件 href 元素上的 <base> 屬性 (<head> 內容的位置)。 |
| NavigateTo | 導覽至指定的 URI。 如果 forceLoad 為 true:
replace 為 true,則會取代瀏覽器歷程記錄中的目前 URI,而不是將新的 URI 推送至歷程記錄堆疊。 |
| LocationChanged | 當導航位置發生變更時觸發的事件。 如需詳細資訊,請參閱位置變更一節。 |
| ToAbsoluteUri | 將相對 URI 轉換成絕對 URI。 |
| ToBaseRelativePath | 根據應用程式的基底 URI,將絕對 URI 轉換成相對於基底 URI 前置詞的 URI。 如需範例,請參閱產生相對於基底 URI 前置詞的 URI 一節。 |
RegisterLocationChangingHandler |
註冊一個事件處理器來處理進入的導覽事件。 呼叫 NavigateTo 總是會叫用處理常式。 |
| GetUriWithQueryParameter | 傳回更新 NavigationManager.Uri 而建構的 URI,並新增、更新或移除單一參數。 如需詳細資訊,請參閱查詢字串一節。 |
| 會員 | Description |
|---|---|
| Uri | 取得目前的絕對 URI。 |
| BaseUri | 取得具有尾端斜線的基底 URI,該 URI 可加在相對 URI 路徑前面,以便生成絕對 URI。 一般而言,BaseUri 會對應至文件 href 元素上的 <base> 屬性 (<head> 內容的位置)。 |
| NavigateTo | 導覽至指定的 URI。 如果 forceLoad 為 true:
replace 為 true,則會取代瀏覽器歷程記錄中的目前 URI,而不是將新的 URI 推送至歷程記錄堆疊。 |
| LocationChanged | 當導航位置發生變更時觸發的事件。 如需詳細資訊,請參閱位置變更一節。 |
| ToAbsoluteUri | 將相對 URI 轉換成絕對 URI。 |
| ToBaseRelativePath | 根據應用程式的基底 URI,將絕對 URI 轉換成相對於基底 URI 前置詞的 URI。 如需範例,請參閱產生相對於基底 URI 前置詞的 URI 一節。 |
| GetUriWithQueryParameter | 傳回更新 NavigationManager.Uri 而建構的 URI,並新增、更新或移除單一參數。 如需詳細資訊,請參閱查詢字串一節。 |
| 會員 | Description |
|---|---|
| Uri | 取得目前的絕對 URI。 |
| BaseUri | 取得具有尾端斜線的基底 URI,該 URI 可加在相對 URI 路徑前面,以便生成絕對 URI。 一般而言,BaseUri 會對應至文件 href 元素上的 <base> 屬性 (<head> 內容的位置)。 |
| NavigateTo | 導覽至指定的 URI。 如果 forceLoad 為 true:
|
| LocationChanged | 當導航位置發生變更時觸發的事件。 |
| ToAbsoluteUri | 將相對 URI 轉換成絕對 URI。 |
| ToBaseRelativePath | 根據應用程式的基底 URI,將絕對 URI 轉換成相對於基底 URI 前置詞的 URI。 如需範例,請參閱產生相對於基底 URI 前置詞的 URI 一節。 |
位置變更
針對 LocationChanged 事件,LocationChangedEventArgs 會提供導覽事件的下列相關資訊:
- Location:新位置的 URL。
-
IsNavigationIntercepted:如果
true,那麼 Blazor 會從瀏覽器攔截導覽。 如果是false,則 NavigationManager.NavigateTo 導致了導覽的發生。
下列元件:
- 使用
Counter選取按鈕時,導覽至應用程式的Counter.razor元件 (NavigateTo)。 - 透過訂閱 NavigationManager.LocationChanged 來處理位置變更事件。
當架構呼叫
HandleLocationChanged時,會解除連結Dispose方法。 將該方法解除連結可允許對元件進行記憶體回收。選取按鈕時,記錄器實作會記錄下列資訊:
BlazorSample.Pages.Navigate: Information: URL of new location: https://localhost:{PORT}/counter
Navigate.razor:
@page "/navigate"
@implements IDisposable
@inject ILogger<Navigate> Logger
@inject NavigationManager Navigation
<h1>Navigate Example</h1>
<button class="btn btn-primary" @onclick="NavigateToCounterComponent">
Navigate to the Counter component
</button>
@code {
private void NavigateToCounterComponent() => Navigation.NavigateTo("counter");
protected override void OnInitialized() =>
Navigation.LocationChanged += HandleLocationChanged;
private void HandleLocationChanged(object? sender, LocationChangedEventArgs e) =>
Logger.LogInformation("URL of new location: {Location}", e.Location);
public void Dispose() => Navigation.LocationChanged -= HandleLocationChanged;
}
如需元件處置的詳細資訊,請參閱 ASP.NET Core Razor 元件處置。
靜態伺服器端轉譯期間的導覽管理員重新導向行為 (靜態 SSR)
對於靜態伺服器端轉譯 (靜態 SSR) 期間的重定向, NavigationManager 依賴於擲回框架捕獲的 a NavigationException ,該框架將錯誤轉換為重定向。 不會呼叫呼叫 NavigateTo 之後存在的程式碼。 使用 Visual Studio 時,偵錯工具會在例外狀況時中斷,要求您在 Visual Studio UI 中使用者 處理此例外狀況類型時取消選取 [中斷] 複選框,以避免偵錯工具停止以進行未來的重新導向。
您可以使用在應用程式專案檔中設定為 的 <BlazorDisableThrowNavigationException> MSBuild 屬性,true選擇加入不再擲回 NavigationException。 此外,呼叫之後 NavigateTo 的程式碼會在之前不會執行時執行。 此行為預設會在 .NET 10 或更新版本 Blazor Web App 的專案範本中啟用:
<BlazorDisableThrowNavigationException>true</BlazorDisableThrowNavigationException>
備註
在 .NET 10 或更新版本中,您可以將 MSBuild 屬性設定NavigationException為 在<BlazorDisableThrowNavigationException>應用程式的專案檔中,選擇加入不擲回 atrue。 若要利用新的 MSBuild 屬性和行為,請將應用程式升級至 .NET 10 或更新版本。
找不到回應
NavigationManager
NotFound提供方法來處理在靜態伺服器端轉譯(靜態 SSR) 或全域互動式轉譯期間找不到要求資源的案例:
靜態 SSR:呼叫
NavigationManager.NotFound會將 HTTP 狀態代碼設定為 404。互動式渲染:向路由器(Blazor)發出
Router訊號,以渲染「找不到內容」。串流轉譯:如果 強化導覽 作用中,串流轉譯 會處理找不到的內容,而不需要重載頁面。 當強化導航遭到封鎖時,架構會通過頁面重新整理將畫面導向至找不到內容的頁面。
備註
下列討論提到一個名為 Razor 的 Not Found 元件可以指派給 Router 元件的 NotFoundPage 參數。 參數會與 NavigationManager.NotFound 搭配運作,稍後在本節中會更詳細地說明此參數。
串流轉譯只能轉譯具有路由的元件,例如 NotFoundPage 指派 (NotFoundPage="...") 或 狀態字碼頁重新執行中介軟體頁面指派 (UseStatusCodePagesWithReExecute)。
DefaultNotFound 404 內容 (“Not found純文本” ) 沒有路由,因此無法在流式渲染期間使用。
備註
.NET 10 或更新版本不支援找不到轉譯片段 (<NotFound>...</NotFound>)。
NavigationManager.NotFound 內容呈現會使用下列事項,不論回應是否已開始(依序):
- 如果設定了 NotFoundEventArgs.Path,則呈現指派頁面的內容。
- 如果設定了
Router.NotFoundPage,則渲染被指定的頁面。 - 如果已設定,狀態代碼頁會重新執行中間件頁面。
- 如果未採用上述任何方法,則不採取任何行動。
狀態代碼頁重新執行中間件 優先處理 UseStatusCodePagesWithReExecute 瀏覽器中與地址路由相關的問題,例如在瀏覽器的地址欄中輸入錯誤的URL,或選擇在應用程式中沒有正確端點的連結。
當元件以靜態方式轉譯(靜態 SSR)並 NavigationManager.NotFound 呼叫時,回應上會設定 404 狀態代碼:
@page "/render-not-found-ssr"
@inject NavigationManager Navigation
@code {
protected override void OnInitialized()
{
Navigation.NotFound();
}
}
若要提供全局互動式渲染的「未找到」內容,請使用未找到頁面(Razor 元件)。
備註
Blazor專案範本包含一個NotFound.razor頁面。 當 NavigationManager.NotFound 被呼叫時,自動渲染此頁面,使得遺失的路由能以一致的使用者體驗處理。
Pages/NotFound.razor:
@page "/not-found"
@layout MainLayout
<h3>Not Found</h3>
<p>Sorry, the content you are looking for does not exist.</p>
元件 NotFound 會被分配給路由器的 NotFoundPage 參數。
NotFoundPage 支援跨狀態代碼頁重新執行中間件使用的路由,包括非Blazor 中間件。
在下列範例中,上述 NotFound 元件會出現在應用程式的 Pages 資料夾中,並傳遞至 NotFoundPage 參數:
<Router AppAssembly="@typeof(Program).Assembly" NotFoundPage="typeof(Pages.NotFound)">
<Found Context="routeData">
<RouteView RouteData="@routeData" />
<FocusOnNavigate RouteData="@routeData" Selector="h1" />
</Found>
</Router>
當元件以全域互動渲染模式渲染時,呼叫NavigationManager.NotFound會向Blazor路由器發出渲染NotFound元件的信號。
@page "/render-not-found-interactive"
@inject NavigationManager Navigation
@if (RendererInfo.IsInteractive)
{
<button @onclick="TriggerNotFound">Trigger Not Found</button>
}
@code {
private void TriggerNotFound()
{
Navigation.NotFound();
}
}
您可以在OnNotFound叫用時使用NavigationManager.NotFound事件來進行通知。 只有在呼叫 NavigationManager.NotFound 時,才會觸發該事件,而不會因任何 404 回應而觸發。 例如,將設定 HttpContextAccessor.HttpContext.Response.StatusCode 為 404 不會觸發 NavigationManager.NotFound/OnNotFound。
實作自訂路由器的應用程式也可以使用 NavigationManager.NotFound。 自訂路由器可以轉譯來自兩個來源的「找不到」內容,視回應的狀態而定:
無論回應狀態如何,頁面的重新執行路徑都可以透過傳遞給 UseStatusCodePagesWithReExecute:
app.UseStatusCodePagesWithReExecute( "/not-found", createScopeForStatusCodePages: true);響應開始後,可以在路由器中訂閱NotFoundEventArgs.Path,並使用
OnNotFoundEvent。@code { [CascadingParameter] public HttpContext? HttpContext { get; set; } private void OnNotFoundEvent(object sender, NotFoundEventArgs e) { // Only execute the logic if HTTP response has started, // because setting NotFoundEventArgs.Path blocks re-execution if (HttpContext?.Response.HasStarted == false) { return; } var type = typeof(CustomNotFoundPage); var routeAttributes = type.GetCustomAttributes<RouteAttribute>(inherit: true); if (routeAttributes.Length == 0) { throw new InvalidOperationException($"The type {type.FullName} " + $"doesn't have a {nameof(RouteAttribute)} applied."); } var routeAttribute = (RouteAttribute)routeAttributes[0]; if (routeAttribute.Template != null) { e.Path = routeAttribute.Template; } } }
以下範例中,採用 互動式伺服器端渲染(互動式 SSR)的元件會根據呼叫位置 OnNotFound 來渲染自訂內容。 如果事件是由下一個 Movie 元件觸發,且在元件初始化時找不到電影,則會顯示自訂訊息表示找不到所請求的電影。 如果事件是由以下範例中的元件觸發 User ,則會顯示另一則訊息顯示找不到該使用者。
以下 NotFoundContext 服務負責管理當元件找不到內容時的上下文與訊息。
NotFoundContext.cs:
public class NotFoundContext
{
public string? Heading { get; private set; }
public string? Message { get; private set; }
public void UpdateContext(string heading, string message)
{
Heading = heading;
Message = message;
}
}
該服務註冊於伺服器端 Program 檔案中:
builder.Services.AddScoped<NotFoundContext>();
該 NotFound 頁面注入 NotFoundContext 並顯示標題與訊息。
Pages/NotFound.razor:
@page "/not-found"
@layout MainLayout
@inject NotFoundContext NotFoundContext
<h3>@NotFoundContext.Heading</h3>
<div>
<p>@NotFoundContext.Message</p>
</div>
Routes組件(Routes.razor)經由參數NotFoundPage將NotFound組件設為「未找到」頁面:
<Router AppAssembly="typeof(Program).Assembly" NotFoundPage="typeof(Pages.NotFound)">
...
</Router>
在下列範例元件中:
- 插入
NotFoundContext服務,以及 NavigationManager。 - 在 中 OnInitializedAsync,
HandleNotFound是指派給OnNotFound事件的事件處理程式。HandleNotFound呼叫NotFoundContext.UpdateContext設定NotFound元件中找不到內容的標題與訊息。 - 元件通常情況下會使用路由參數的標識碼,從資料存放庫中取得電影或使用者,例如資料庫。 在下列範例中,不會傳回任何實體 (
null) 來模擬找不到實體時會發生什麼事。 - 當 OnInitializedAsync 未傳回任何實體時,會呼叫
NavigationManager.NotFound,進而觸發OnNotFound事件和HandleNotFound事件處理程式。 路由器會顯示 「找不到」內容。 -
HandleNotFound方法在 IDisposable.Dispose 元件處置時解除連結。
Movie 元件 (Movie.razor):
@page "/movie/{Id:int}"
@implements IDisposable
@inject NavigationManager NavigationManager
@inject NotFoundContext NotFoundContext
<div>
No matter what ID is used, no matching movie is returned
from the call to GetMovie().
</div>
@code {
[Parameter]
public int Id { get; set; }
protected override async Task OnInitializedAsync()
{
NavigationManager.OnNotFound += HandleNotFound;
var movie = await GetMovie(Id);
if (movie == null)
{
NavigationManager.NotFound();
}
}
private void HandleNotFound(object? sender, NotFoundEventArgs e)
{
NotFoundContext.UpdateContext("Movie Not Found",
"Sorry! The requested movie wasn't found.");
}
private async Task<MovieItem[]?> GetMovie(int id)
{
// Simulate no movie with matching id found
return await Task.FromResult<MovieItem[]?>(null);
}
void IDisposable.Dispose()
{
NavigationManager.OnNotFound -= HandleNotFound;
}
public class MovieItem
{
public int Id { get; set; }
public string? Title { get; set; }
}
}
User 元件 (User.razor):
@page "/user/{Id:int}"
@implements IDisposable
@inject NavigationManager NavigationManager
@inject NotFoundContext NotFoundContext
<div>
No matter what ID is used, no matching user is returned
from the call to GetUser().
</div>
@code {
[Parameter]
public int Id { get; set; }
protected override async Task OnInitializedAsync()
{
NavigationManager.OnNotFound += HandleNotFound;
var user = await GetUser(Id);
if (user == null)
{
NavigationManager.NotFound();
}
}
private void HandleNotFound(object? sender, NotFoundEventArgs e)
{
NotFoundContext.UpdateContext("User Not Found",
"Sorry! The requested user wasn't found.");
}
private async Task<UserItem[]?> GetUser(int id)
{
// Simulate no user with matching id found
return await Task.FromResult<UserItem[]?>(null);
}
void IDisposable.Dispose()
{
NavigationManager.OnNotFound -= HandleNotFound;
}
public class UserItem
{
public int Id { get; set; }
public string? Name { get; set; }
}
}
為了在本地示範中使用測試應用程式來訪問上述元件,請在NavMenu元件中創建項目(NavMenu.razor),以便連接到Movie和User元件。 在以下範例中,作為路由參數傳遞的實體ID是模擬值,這些值對元件沒有實際作用,因此元件將模擬無法找到電影或使用者的情境。
在 NavMenu.razor 中:
<div class="nav-item px-3">
<NavLink class="nav-link" href="movie/1">
<span class="bi bi-list-nested-nav-menu" aria-hidden="true"></span> Movie
</NavLink>
</div>
<div class="nav-item px-3">
<NavLink class="nav-link" href="user/2">
<span class="bi bi-list-nested-nav-menu" aria-hidden="true"></span> User
</NavLink>
</div>
強化的導航與表單處理
本章節適用於 Blazor Web App項。
Blazor Web App 有兩種類型的路由功能,用於頁面導覽和處理表單請求:
- 一般導覽 (跨文件導覽):針對要求 URL 觸發全頁重新載入。
- 增強式導覽 (相同文件導覽):Blazor 會攔截要求並改為執行
fetch要求。 然後 Blazor 會將回應內容嵌入到頁面的 DOM。 Blazor 的增強式導覽和表單處理可避免需要完整頁面重新載入,並可保留更多頁面狀態,因此頁面載入速度較快,通常不會遺失使用者在頁面上的捲動位置。
在以下情況中,增強式導覽可供使用:
- 使用 Blazor Web App 式指令碼 (
blazor.web.js),而不是 Blazor Server 指令碼 (blazor.server.js) 或 Blazor WebAssembly 指令碼 (blazor.webassembly.js)。 - 該功能不會明確停用。
- 目的地URL位於內部基底URI空間(應用程式的基底路徑)內,且頁面連結的屬性未
data-enhance-nav設定為false。
如果已啟用伺服器端路由和增強式瀏覽,則只會針對從互動式執行階段起始的程式設計導覽來叫用位置變更處理常式。 在未來版本中,其他類型的導覽(例如點擊連結)也可能會叫用位置變更處理常式。
當增強的瀏覽功能出現時,通常會叫用註冊於互動伺服器及 WebAssembly 執行階段的LocationChanged事件處理常式。 在某些情況下,位置變更處理程序可能不會攔截強化的導航。 例如,使用者可能會在互動式執行階段變得可用之前切換至另一個頁面。 因此,很重要的是應用程式邏輯不依賴叫用位置變更處理常式,因為無法保證處理常式的執行。
呼叫 NavigateTo 時:
- 如果
forceLoad為false,則為預設值:- 當增強式導覽可在目前 URL 取得時,Blazor 的增強式導覽會啟動。
- 否則,Blazor 會針對要求的 URL 執行完整頁面重新載入。
- 如果
forceLoad為true:Blazor 會針對要求的 URL 執行完整頁面重新載入,無論增強式導覽是否可供使用。
您可以呼叫 NavigationManager.Refresh(bool forceLoad = false) 來重新整理目前的頁面,其一律會執行增強式導覽 (如果可用)。 如果增強式導覽無法使用,Blazor 會執行完整頁面重新載入。
Navigation.Refresh();
將 true 傳遞至 forceLoad 參數,以確保一律會執行完整頁面重新載入,即使增強式導覽可供使用:
Navigation.Refresh(true);
預設會啟用增強式導覽,但可以使用 data-enhance-nav HTML 屬性,以階層方式及依每一連結為基礎來控制。
下列範例會停用增強式導覽:
<a href="redirect" data-enhance-nav="false">
GET without enhanced navigation
</a>
<ul data-enhance-nav="false">
<li>
<a href="redirect">GET without enhanced navigation</a>
</li>
<li>
<a href="redirect-2">GET without enhanced navigation</a>
</li>
</ul>
如果目的地為非 Blazor 端點,則不適用增強式導覽,且用戶端 JavaScript 會以完整頁面載入方式重試。 這可確保框架不會對不應修補至現有頁面的外部頁面產生混淆。
若要啟用增強式表單處理,請將 Enhance 參數新增至 EditForm 表單或將 data-enhance 屬性新增至 HTML 表單 (<form>):
<EditForm ... Enhance ...>
...
</EditForm>
<form ... data-enhance ...>
...
</form>
增強式表單處理不是階層式,而且不會流向子表單:
不支援:您無法在表單的上階元素上設定增強式導覽,以啟用表單的增強式導覽。
<div ... data-enhance ...>
<form ...>
<!-- NOT enhanced -->
</form>
</div>
增強型表單提交僅適用於 Blazor 端點。 將增強式表單張貼至非 Blazor 端點會導致錯誤。
若要停用增強式導覽:
- 針對 EditForm,請從表單元素中移除 Enhance 參數 (或將其設定為
false:Enhance="false")。 - 針對 HTML
<form>,請從表單元素移除data-enhance屬性 (或將其設定為false:data-enhance="false")。
如果更新的內容不屬於伺服器渲染的一部分,Blazor 的增強式導覽和表單處理可能會復原對 DOM 的動態變更。 若要保留元素的內容,請使用 data-permanent 屬性。
在下列範例中,當頁面載入時,指令碼會動態更新 <div> 元素的內容:
<div data-permanent>
...
</div>
在用戶端上啟動 Blazor 之後,您可以使用 enhancedload 事件來接聽增強式頁面更新。 允許將可能因增強頁面更新而復原的變更重新套用至 DOM。
Blazor.addEventListener('enhancedload', () => console.log('Enhanced update!'));
若要全域停用增強式導覽和表單處理,請參閱 ASP.NET Core Blazor 啟動。
使用 靜態伺服器端渲染 (靜態 SSR)增強導航時,在載入 JavaScript 時需要特別注意。 如需詳細資訊,請參閱 ASP.NET Core Blazor JavaScript 與靜態伺服器端轉譯(static SSR)。
產生相對於基礎 URI 前綴的 URI
根據應用程式的基底 URI,ToBaseRelativePath 會將絕對 URI 轉換成相對於基底 URI 前置詞的 URI。
請考慮下列範例:
try
{
baseRelativePath = Navigation.ToBaseRelativePath(inputURI);
}
catch (ArgumentException ex)
{
...
}
如果應用程式的基底 URI 是 https://localhost:8000,則會取得下列結果:
- 傳遞
https://localhost:8000/segment於inputURI中會導致baseRelativePath為segment。 - 傳遞
https://localhost:8000/segment1/segment2於inputURI中會導致baseRelativePath為segment1/segment2。
如果應用程式的基底 URI 不符合 inputURI 的基底 URI,則會擲回 ArgumentException。
在 https://localhost:8001/segment 中傳入 inputURI 會產生下列例外狀況:
System.ArgumentException: 'The URI 'https://localhost:8001/segment' is not contained by the base URI 'https://localhost:8000/'.'
導覽歷程記錄狀態
NavigationManager 會使用瀏覽器的歷程記錄 API 來維護與應用程式進行的每個位置變更相關聯的導覽歷程記錄狀態。 維護歷程記錄狀態在外部重新導向案例中特別有用,例如 向外部識別提供者驗證使用者時,。 如需詳細資訊,請參閱導覽選項一節。
導覽選項
將 NavigationOptions 傳遞至 NavigateTo 以控制下列行為:
-
ForceLoad:略過用戶端路由,並強制瀏覽器從伺服器載入新頁面,無論 URI 是否由用戶端路由器處理。 預設值是
false。 -
ReplaceHistoryEntry:取代歷程堆疊中的當前項目。 如果為
false,則將新項目附加至歷程記錄堆疊。 預設值是false。 - HistoryEntryState:取得或設定要附加至歷史記錄項目的狀態。
Navigation.NavigateTo("/path", new NavigationOptions
{
HistoryEntryState = "Navigation state"
});
如需在處理位置變更時取得與目標歷程記錄項目相關聯狀態的詳細資訊,請參閱處理/防止位置變更一節。
查詢字串
使用 [SupplyParameterFromQuery] 屬性來指定元件參數來自查詢字串。
使用 [SupplyParameterFromQuery] 屬性搭配 [Parameter] 屬性來指定可路由元件的元件參數來自查詢字串。
備註
元件參數只能接收具有 @page 指示詞的可路由元件中的查詢參數值。
只有可路由元件會直接接收查詢參數,以避免破壞由上而下的資訊流程,並讓架構和應用程式的參數處理順序清楚。 此設計可避免撰寫時假設特定參數處理順序的應用程式程式碼中發生細微的錯誤。 您可以自由定義自訂串聯參數,或直接指派給一般元件參數,以便將查詢參數值傳遞至不可路由的元件。
從查詢字串提供的元件參數可支援下列型別:
-
bool、DateTime、decimal、double、float、、Guidint、long、、string。 - 上述型別的可為空變體。
- 上述類型的陣列,無論是可為空值還是不可為空值。
會針對指定的型別 (CultureInfo.InvariantCulture) 套用正確的不因文化特性而異的格式。
指定 [SupplyParameterFromQuery] 屬性的 Name 屬性,以使用與元件參數名稱不同的查詢參數名稱。 在下列範例中,元件參數的 C# 名稱是 {COMPONENT PARAMETER NAME}。 為 {QUERY PARAMETER NAME} 預留位置指定了不同的查詢參數名稱:
不同於元件參數屬性 ([Parameter]),除了 [SupplyParameterFromQuery] 之外,private 屬性還可以標示為 public。
[SupplyParameterFromQuery(Name = "{QUERY PARAMETER NAME}")]
private string? {COMPONENT PARAMETER NAME} { get; set; }
和元件參數屬性 ([Parameter]) 一樣,[SupplyParameterFromQuery] 屬性在 .NET 6/7 中始終為 public 屬性。 在 .NET 8 或更新版本中,[SupplyParameterFromQuery] 屬性可以標示為 public 或 private。
[Parameter]
[SupplyParameterFromQuery(Name = "{QUERY PARAMETER NAME}")]
public string? {COMPONENT PARAMETER NAME} { get; set; }
在下列範例中,URL 是 /search?filter=scifi%20stars&page=3&star=LeVar%20Burton&star=Gary%20Oldman:
-
Filter屬性會解析為scifi stars。 -
Page屬性會解析為3。 -
Stars陣列會從名為star(Name = "star") 的查詢參數填入,並解析為LeVar Burton和Gary Oldman。
備註
下列可路由頁面元件中的查詢字串參數也可以在不含 指示詞的非路由@page元件中運作(例如,作為其他元件中使用的共享Search.razor元件 Search)。
Search.razor:
@page "/search"
<h1>Search Example</h1>
<p>Filter: @Filter</p>
<p>Page: @Page</p>
@if (Stars is not null)
{
<p>Stars:</p>
<ul>
@foreach (var name in Stars)
{
<li>@name</li>
}
</ul>
}
@code {
[SupplyParameterFromQuery]
private string? Filter { get; set; }
[SupplyParameterFromQuery]
private int? Page { get; set; }
[SupplyParameterFromQuery(Name = "star")]
private string[]? Stars { get; set; }
}
Search.razor:
@page "/search"
<h1>Search Example</h1>
<p>Filter: @Filter</p>
<p>Page: @Page</p>
@if (Stars is not null)
{
<p>Stars:</p>
<ul>
@foreach (var name in Stars)
{
<li>@name</li>
}
</ul>
}
@code {
[Parameter]
[SupplyParameterFromQuery]
public string? Filter { get; set; }
[Parameter]
[SupplyParameterFromQuery]
public int? Page { get; set; }
[Parameter]
[SupplyParameterFromQuery(Name = "star")]
public string[]? Stars { get; set; }
}
使用 GetUriWithQueryParameter 來在目前 URL 上新增、變更或移除一或多個查詢參數:
@inject NavigationManager Navigation
...
Navigation.GetUriWithQueryParameter("{NAME}", {VALUE})
針對上述範例:
-
{NAME}預留位置指定查詢參數名稱。{VALUE}預留位置會將值指定為支援的型別。 本節稍後會列出支援的型別。 - 傳回的字串為當前 URL 加上一個參數。
- 如果查詢參數名稱不存在於目前 URL 中,則新增。
- 如果查詢參數存在於目前的 URL 中,則更新為所提供的值。
- 如果所提供值的型別為可為空,且值為
null,則移除。
- 會針對指定的型別 (CultureInfo.InvariantCulture) 套用正確的不因文化特性而異的格式。
- 查詢參數名稱和值會以 URL 編碼。
- 如果有多個該類型的執行個體,則會替換所有具有相符查詢參數名稱的值。
呼叫 GetUriWithQueryParameters 以建立自 Uri 建構的 URI,並新增、更新或移除多個參數。 針對每個值,架構會使用 value?.GetType() 來判斷每個查詢參數的執行階段型別,並選取正確的不因文化特性而異格式。 架構會針對不被支援的型別拋出錯誤。
@inject NavigationManager Navigation
...
Navigation.GetUriWithQueryParameters({PARAMETERS})
{PARAMETERS} 預留位置是 IReadOnlyDictionary<string, object>。
將 URI 字串傳遞至 GetUriWithQueryParameters,以從提供的 URI 產生新的 URI,並新增、更新或移除多個參數。 針對每個值,架構會使用 value?.GetType() 來判斷每個查詢參數的執行階段型別,並選取正確的不因文化特性而異格式。 架構會針對不被支援的型別拋出錯誤。 本節稍後會列出支援的型別。
@inject NavigationManager Navigation
...
Navigation.GetUriWithQueryParameters("{URI}", {PARAMETERS})
-
{URI}預留位置是含有或不含查詢字串的 URI。 -
{PARAMETERS}預留位置是IReadOnlyDictionary<string, object>。
支援的型別和路由約束條件所支援的型別相同:
boolDateOnlyDateTimedecimaldoublefloatGuidintlongstringTimeOnly
支援的類型包括:
- 上述型別的可為空變體。
- 上述類型的陣列,無論是可為空值還是不可為空值。
警告
透過預設啟用的壓縮,避免建立安全 (經過驗證/授權) 的互動式伺服器端元件來呈現來自不受信任來源的資料。 不受信任的來源包括路由參數、查詢字串、來自 JS Interop 的資料,以及第三方使用者可以控制的任何其他資料來源 (資料庫、外部服務)。 如需詳細資訊,請參閱 ASP.NET Core BlazorSignalR 指引和 ASP.NET Core Blazor 互動式伺服器端轉譯的威脅防護指引。
當查詢參數存在時,替換其值
Navigation.GetUriWithQueryParameter("full name", "Morena Baccarin")
| 目前的 URL | 產生的 URL |
|---|---|
scheme://host/?full%20name=David%20Krumholtz&age=42 |
scheme://host/?full%20name=Morena%20Baccarin&age=42 |
scheme://host/?fUlL%20nAmE=David%20Krumholtz&AgE=42 |
scheme://host/?full%20name=Morena%20Baccarin&AgE=42 |
scheme://host/?full%20name=Jewel%20Staite&age=42&full%20name=Summer%20Glau |
scheme://host/?full%20name=Morena%20Baccarin&age=42&full%20name=Morena%20Baccarin |
scheme://host/?full%20name=&age=42 |
scheme://host/?full%20name=Morena%20Baccarin&age=42 |
scheme://host/?full%20name= |
scheme://host/?full%20name=Morena%20Baccarin |
參數不存在時,附加查詢參數和值
Navigation.GetUriWithQueryParameter("name", "Morena Baccarin")
| 目前的 URL | 產生的 URL |
|---|---|
scheme://host/?age=42 |
scheme://host/?age=42&name=Morena%20Baccarin |
scheme://host/ |
scheme://host/?name=Morena%20Baccarin |
scheme://host/? |
scheme://host/?name=Morena%20Baccarin |
參數值為 null 時,移除查詢參數
Navigation.GetUriWithQueryParameter("full name", (string)null)
| 目前的 URL | 產生的 URL |
|---|---|
scheme://host/?full%20name=David%20Krumholtz&age=42 |
scheme://host/?age=42 |
scheme://host/?full%20name=Sally%20Smith&age=42&full%20name=Summer%20Glau |
scheme://host/?age=42 |
scheme://host/?full%20name=Sally%20Smith&age=42&FuLl%20NaMe=Summer%20Glau |
scheme://host/?age=42 |
scheme://host/?full%20name=&age=42 |
scheme://host/?age=42 |
scheme://host/?full%20name= |
scheme://host/ |
新增、更新和移除查詢參數
在以下範例中:
- 如果存在,移除
name。 - 如果
age不存在,則會新增並具有值25(int)。 如果存在,則將age更新為25的值。 -
eye color會新增或更新為green的值。
Navigation.GetUriWithQueryParameters(
new Dictionary<string, object?>
{
["name"] = null,
["age"] = (int?)25,
["eye color"] = "green"
})
| 目前的 URL | 產生的 URL |
|---|---|
scheme://host/?name=David%20Krumholtz&age=42 |
scheme://host/?age=25&eye%20color=green |
scheme://host/?NaMe=David%20Krumholtz&AgE=42 |
scheme://host/?age=25&eye%20color=green |
scheme://host/?name=David%20Krumholtz&age=42&keepme=true |
scheme://host/?age=25&keepme=true&eye%20color=green |
scheme://host/?age=42&eye%20color=87 |
scheme://host/?age=25&eye%20color=green |
scheme://host/? |
scheme://host/?age=25&eye%20color=green |
scheme://host/ |
scheme://host/?age=25&eye%20color=green |
支援可列舉的值
在以下範例中:
-
full name會新增或更新為Morena Baccarin,單一值。 -
ping參數會新增或取代為35、16、87和240。
Navigation.GetUriWithQueryParameters(
new Dictionary<string, object?>
{
["full name"] = "Morena Baccarin",
["ping"] = new int?[] { 35, 16, null, 87, 240 }
})
| 目前的 URL | 產生的 URL |
|---|---|
scheme://host/?full%20name=David%20Krumholtz&ping=8&ping=300 |
scheme://host/?full%20name=Morena%20Baccarin&ping=35&ping=16&ping=87&ping=240 |
scheme://host/?ping=8&full%20name=David%20Krumholtz&ping=300 |
scheme://host/?ping=35&full%20name=Morena%20Baccarin&ping=16&ping=87&ping=240 |
scheme://host/?ping=8&ping=300&ping=50&ping=68&ping=42 |
scheme://host/?ping=35&ping=16&ping=87&ping=240&full%20name=Morena%20Baccarin |
使用新增或修改的查詢字串導覽
若要使用新增或修改的查詢字串導覽,請將產生的 URL 傳遞至 NavigateTo。
下列範例會呼叫:
-
GetUriWithQueryParameter 來使用
name的值以新增或取代Morena Baccarin查詢參數。 - 呼叫 NavigateTo 以觸發導覽至新 URL。
Navigation.NavigateTo(
Navigation.GetUriWithQueryParameter("name", "Morena Baccarin"));
要求的查詢字串是從 NavigationManager.Uri 屬性取得:
@inject NavigationManager Navigation
...
var query = new Uri(Navigation.Uri).Query;
若要剖析查詢字串的參數,其中一種方法是使用 URLSearchParams 搭配 JavaScript (JS) Interop:
export createQueryString = (string queryString) => new URLSearchParams(queryString);
如需 JavaScript 隔離與 JavaScript 模組的詳細資訊,請參閱在 ASP.NET Core Blazor 中從 .NET 方法呼叫 JavaScript 函式。
導航至命名元素
使用下列方法,使用指向元素的雜湊值 (#) 參考,導覽至具名元素。 元件內的元素和外部元件中的元素皆使用根相對路徑進行路由。 前置正斜線符號 (/) 是可選的。
下列方法的範例會示範如何在 id 元件中導航到具有 targetElement 的 Counter 的元素:
具有
<a>的錨點元素 (href):<a href="/counter#targetElement">具有 NavLink 的
href元件:<NavLink href="/counter#targetElement">NavigationManager.NavigateTo 傳遞相對 URL:
Navigation.NavigateTo("/counter#targetElement");
以下範例示範如何導航至元件內的命名 H2 標題及外部元件。
在 Home (Home.razor) 和 Counter (Counter.razor) 元件中,將下列標記放置在現有元件標記的底部,以做為導覽目標。
<div> 會建立人工垂直空間來示範瀏覽器捲動行為:
<div class="border border-info rounded bg-info" style="height:500px"></div>
<h2 id="targetElement">Target H2 heading</h2>
<p>Content!</p>
將下列 FragmentRouting 元件新增至應用程式。
FragmentRouting.razor:
@page "/fragment-routing"
@inject NavigationManager Navigation
<PageTitle>Fragment routing</PageTitle>
<h1>Fragment routing to named elements</h1>
<ul>
<li>
<a href="/fragment-routing#targetElement">
Anchor in this component
</a>
</li>
<li>
<a href="/#targetElement">
Anchor to the <code>Home</code> component
</a>
</li>
<li>
<a href="/counter#targetElement">
Anchor to the <code>Counter</code> component
</a>
</li>
<li>
<NavLink href="/fragment-routing#targetElement">
Use a `NavLink` component in this component
</NavLink>
</li>
<li>
<button @onclick="NavigateToElement">
Navigate with <code>NavigationManager</code> to the
<code>Counter</code> component
</button>
</li>
</ul>
<div class="border border-info rounded bg-info" style="height:500px"></div>
<h2 id="targetElement">Target H2 heading</h2>
<p>Content!</p>
@code {
private void NavigateToElement()
{
Navigation.NavigateTo("/counter#targetElement");
}
}
處理/防止位置變更
RegisterLocationChangingHandler 會註冊一個處理程序來處理傳入的導覽事件。 LocationChangingContext 提供的處理程序內容包含下列屬性:
- TargetLocation:取得目標位置。
- HistoryEntryState:獲取與目標歷程記錄項目相關聯的狀態。
- IsNavigationIntercepted:檢查導覽是否從連結被攔截。
- CancellationToken:取得 CancellationToken,以判斷導覽是否已取消,例如,以判斷使用者是否觸發了不同的導覽。
- PreventNavigation:用於防止導覽繼續進行。
元件可以用 OnAfterRender{Async} 生命週期法註冊多個位置變更處理常式。 導覽會呼叫整個應用程式(跨多個元件)中註冊的所有位置變更處理常式,並在任何內部導覽過程中平行執行它們。 除了調用 NavigateTo 處理程式之外:
- 選取內部連結時,這是指向應用程式基底路徑下 URL 的連結。
- 在瀏覽器中使用向前和返回按鈕導覽時。
處理程序只會針對應用程式內部的導覽執行。 如果使用者選取導覽至不同網站的連結,或手動將網址列變更為不同的網站,則不會執行位置變更處理常式。
實作 IDisposable 並撤銷已註冊的處理常式,來取消註冊它們。 如需詳細資訊,請參閱 ASP.NET Core Razor 元件處置。
這很重要
處理位置變更時,請勿嘗試透過 JavaScript (JS) Interop 執行 DOM 清除工作。 在用戶端的
在下列範例中,會註冊位置改變的處理常式用於導航事件。
NavHandler.razor:
@page "/nav-handler"
@implements IDisposable
@inject NavigationManager Navigation
<p>
<button @onclick="@(() => Navigation.NavigateTo("/"))">
Home (Allowed)
</button>
<button @onclick="@(() => Navigation.NavigateTo("/counter"))">
Counter (Prevented)
</button>
</p>
@code {
private IDisposable? registration;
protected override void OnAfterRender(bool firstRender)
{
if (firstRender)
{
registration =
Navigation.RegisterLocationChangingHandler(OnLocationChanging);
}
}
private ValueTask OnLocationChanging(LocationChangingContext context)
{
if (context.TargetLocation == "/counter")
{
context.PreventNavigation();
}
return ValueTask.CompletedTask;
}
public void Dispose() => registration?.Dispose();
}
由於內部導覽可以非同步取消,因此可能會對已註冊的處理程序進行多次重疊的呼叫。 例如,當使用者快速選取頁面上的返回按鈕,或在執行導覽之前選取多個連結時,可能會發生多個處理常式呼叫。 以下是非同步導覽邏輯的摘要:
- 如果已註冊任何位置變更處理常式,則所有導覽一開始都會恢復,然後如果導覽未取消,則重新執行。
- 如果提出重疊的導覽要求,最新的要求一律會取消先前的要求,這表示以下:
- 應用程式可能會將多個返回和向前按鈕選取項目視為單一選取項目。
- 如果使用者在導覽完成之前選取多個連結,選取的最後一個連結會決定導覽。
如需傳遞 NavigationOptions 至 NavigateTo 以控制導覽歷程記錄堆疊的項目和狀態的詳細資訊,請參閱導覽選項一節。
如需其他範例程式碼,請參閱 NavigationManagerComponent 中的 BasicTestApp (dotnet/aspnetcore 參考來源)。
備註
通常,指向 .NET 參考來源的文件連結會載入存放庫的預設分支,這代表 .NET 下一版本的最新開發進度。 若要選取特定發行版本的標籤,請使用「切換分支或標籤」下拉式清單。 如需詳細資訊,請參閱如何選取 ASP.NET Core 原始程式碼 (dotnet/AspNetCore.Docs #26205) 的版本標籤。
只要經過轉譯,NavigationLock 元件就會攔截導覽事件,在決定繼續或取消之前,有效地「鎖定」任何指定的導覽。 當導覽攔截的範圍可設定為元件的生命週期時使用 NavigationLock。
NavigationLock 參數:
-
ConfirmExternalNavigation 會設定瀏覽器對話方塊,以提示使用者確認或取消外部導覽。 預設值是
false。 要顯示確認對話方塊,必須先與頁面進行初始準備互動,然後才能在瀏覽器的網址列中使用 URL 來觸發外部導覽。 如需互動需求的詳細資訊,請參閱 Window:beforeunload事件。 - OnBeforeInternalNavigation 用來設定內部導覽事件的回呼函數。
在下列 NavLock 組件中:
- 在導覽至
https://www.microsoft.com之前,使用者必須確認是否嘗試點擊 Microsoft 網站的連結才能成功。 - 如果使用者拒絕透過由
JavaScript ( 觸發的) 互通呼叫 對話方塊確認導覽,則會呼叫 以防止導覽發生。
NavLock.razor:
@page "/nav-lock"
@inject IJSRuntime JSRuntime
@inject NavigationManager Navigation
<NavigationLock ConfirmExternalNavigation="true"
OnBeforeInternalNavigation="OnBeforeInternalNavigation" />
<p>
<button @onclick="Navigate">Navigate</button>
</p>
<p>
<a href="https://www.microsoft.com">Microsoft homepage</a>
</p>
@code {
private void Navigate()
{
Navigation.NavigateTo("/");
}
private async Task OnBeforeInternalNavigation(LocationChangingContext context)
{
var isConfirmed = await JSRuntime.InvokeAsync<bool>("confirm",
"Are you sure you want to navigate to the root page?");
if (!isConfirmed)
{
context.PreventNavigation();
}
}
}
如需其他範例程式碼,請參閱 ConfigurableNavigationLock 中的 BasicTestApp 元件 (dotnet/aspnetcore 參考來源)。
透過反射動態產生 NavLink 的元件
NavLink 元件項目可以透過反射從應用程式的元件中動態建立。 下列範例示範進一步自訂的一般方法。
針對下列示範,應用程式元件會使用一致的標準命名慣例:
- 可路由的元件檔案名稱會使用大駝峰式命名法†,例如
Pages/ProductDetail.razor。 - 可路由元件的檔案路徑會與其使用連字命名法(kebab case)的 URL 相符,也就是在元件的路由範本中的單字之間以連字號分隔。 例如,路由範本為
ProductDetail(/product-detail) 的@page "/product-detail"元件會在瀏覽器中於相對 URL/product-detail被請求。
†Pascal 命名法(大駝峰式命名法)是一種命名慣例,其特點是不含空格和標點符號,並且每個單字的第一個字母都大寫,包括第一個單字。
‡烤肉串式命名格式是不含空格和標點符號的命名慣例,並且在字組之間使用小寫字母和連字號。
在預設 Razor 頁面底下 NavMenu 元件 (NavMenu.razor) 的 Home 標記中,會從集合中新增 NavLink 元件:
<div class="nav-scrollable"
onclick="document.querySelector('.navbar-toggler').click()">
<nav class="flex-column">
<div class="nav-item px-3">
<NavLink class="nav-link" href="" Match="NavLinkMatch.All">
<span class="bi bi-house-door-fill-nav-menu"
aria-hidden="true"></span> Home
</NavLink>
</div>
+ @foreach (var name in GetRoutableComponents())
+ {
+ <div class="nav-item px-3">
+ <NavLink class="nav-link"
+ href="@Regex.Replace(name, @"(\B[A-Z]|\d+)", "-$1").ToLower()">
+ @Regex.Replace(name, @"(\B[A-Z]|\d+)", " $1")
+ </NavLink>
+ </div>
+ }
</nav>
</div>
GetRoutableComponents 區塊中的 @code 方法:
public IEnumerable<string> GetRoutableComponents() =>
Assembly.GetExecutingAssembly()
.ExportedTypes
.Where(t => t.IsSubclassOf(typeof(ComponentBase)))
.Where(c => c.GetCustomAttributes(inherit: true)
.OfType<RouteAttribute>()
.Any())
.Where(c => c.Name != "Home" && c.Name != "Error")
.OrderBy(o => o.Name)
.Select(c => c.Name);
上述範例不會在轉譯的元件清單中包含下列頁面:
-
Home頁面: 頁面會與自動產生的連結分開列出,因為它應該出現在清單頂端,並設定Match參數。 -
Error頁面: 錯誤頁面僅由框架導向,不應列出。
若要在範例應用程式中示範前述程式碼,請取得 Blazor Web App 或 Blazor WebAssembly 範例應用程式。