使用路由模板

 

用户请求你的 Web 应用中的页面时,可以使用 URI 中的信息指定要查看的内容。 例如:

http://www.contoso.com/pizzas/margherita?extratopping=pineapple

在协议和网站地址之后,此 URI 指示用户想要了解玛格丽特披萨。 此外,问号后的查询字符串显示他们有兴趣额外添加一份菠萝配料。 在 Blazor 中,使用路由来确保将每个请求发送到最适合的组件,并且该组件具有显示用户所需内容的全部信息。 在本例中,你可能希望将请求发送到 Pizzas 组件,并使该组件显示玛格丽特披萨,并显示有关添加菠萝配料的信息。

Blazor 使用名为 Router 组件的专用组件路由请求。 它在 App.razor 中配置如下:

<Router AppAssembly="@typeof(Program).Assembly">
	<Found Context="routeData">
		<RouteView RouteData="@routeData" DefaultLayout="@typeof(MainLayout)" />
	</Found>
	<NotFound>
		<p>Sorry, we haven't found any pizzas here.</p>
	</NotFound>
</Router>

应用启动时,Blazor 会检查 AppAssembly 属性,以了解它应扫描哪个程序集。 它会扫描该程序集,以寻找具有 RouteAttribute 的组件。 Blazor 使用这些值编译 RouteData 对象,该对象指定如何将请求路由到组件。 编写应用代码时,可以在每个组件中使用 @page 指令来修复 RouteAttribute。

在以上代码中,<Found> 标记指定在运行时处理路由的组件:RouteView 组件。 此组件接收 RouteData 对象以及来自 URI 或查询字符串的任何参数。 然后,它呈现指定的组件及其布局。 可以使用 <Found> 标记来指定默认布局,当所选组件未通过 @layout 指令指定布局时,将使用该布局。 本模块稍后会详细介绍这些布局。

在 <Router> 组件中,还可使用 <NotFound> 标记指定在不存在匹配路由时返回给用户的内容。 上面的示例返回单个 <p> 段落,但你可以呈现更复杂的 HTML。 例如,可能包括指向主页或站点管理员联系人页面的链接。

使用 @page 指令

 

在 Blazor 组件中,@page 指令指定该组件应直接处理请求。 可以在 @page 指令中指定 RouteAttribute,方法是以字符串的形式传递它。 例如,使用此属性指定页面处理对 /Pizzas 路由的请求:

@page "/Pizzas"

如果要指定到组件的多个路由,请使用两个或更多 @page 指令,如本例所示:

@page "/Pizzas"
@page "/CustomPizzas"

获取位置信息,并使用 NavigationManager 导航

 

假设你要编写一个组件来处理用户请求的 URI,例如 http://www.contoso.com/pizzas/margherita/?extratopping=pineapple

编写组件时,可能需要访问导航信息,例如:

  • 当前完整 URI,例如 http://www.contoso.com/pizzas/margherita?extratopping=pineapple
  • 基本 URI,例如 http://www.contoso.com/
  • 基本相对路径,例如 pizzas/margherita
  • 查询字符串,例如 ?extratopping=pineapple

可以使用 NavigationManager 对象来获取所有这些值。 必须将对象注入组件,然后才能访问其属性。 此代码使用 NavigationManager 对象获取网站的基本 URI,然后使用它来设置主页的链接:

@page "/pizzas"
@inject NavigationManager NavManager

<h1>Buy a Pizza</h1>

<p>I want to order a: @PizzaName</p>

<a href=@HomePageURI>Home Page</a>

@code {
	[Parameter]
	public string PizzaName { get; set; }
	
	public string HomePageURI { get; set; }
	
	protected override void OnInitialized()
	{
		HomePageURI = NavManager.BaseUri;
	}
}

若要访问查询字符串,必须分析完整 URI。 使用 Microsoft.AspNetCore.WebUtilities 程序集中的 QueryHelpers 类执行此分析:

@page "/pizzas"
@using Microsoft.AspNetCore.WebUtilities
@inject NavigationManager NavManager

<h1>Buy a Pizza</h1>

<p>I want to order a: @PizzaName</p>

<p>I want to add this topping: @ToppingName</p>

@code {
	[Parameter]
	public string PizzaName { get; set; }
	
	private string ToppingName { get; set; }
	
	protected override void OnInitialized()
	{
		var uri = NavManager.ToAbsoluteUri(NavManager.Uri);
		if (QueryHelpers.ParseQuery(uri.Query).TryGetValue("extratopping", out var extraTopping))
		{
			ToppingName = System.Convert.ToString(extraTopping);
		}
	}
}

部署上述组件后,如果用户请求了 URI http://www.contoso.com/pizzas?extratopping=Pineapple,他们将在呈现的页面中看到消息“我想添加以下配料:菠萝”。

还可通过调用 NavigationManager.NavigateTo() 方法,使用 NavigationManager 对象将用户转交给代码中的另一个组件:

@page "/pizzas/{pizzaname}"
@inject NavigationManager NavManager

<h1>Buy a Pizza</h1>

<p>I want to order a: @PizzaName</p>

<button class="btn" @onclick="NavigateToPaymentPage">
	Buy this pizza!
</button>

@code {
	[Parameter]
	public string PizzaName { get; set; }
	
	private void NavigateToPaymentPage()
	{
		NavManager.NavigateTo("buypizza");
	}
}

 

在以上示例中,代码用于获取 NavigationManager.BaseUri 值,并使用该值将 <a> 标记的 href 属性设置为主页。 在 Blazor 中,使用 NavLink 组件来呈现 <a> 标记,因为它在链接的 href 属性与当前 URL 匹配时将切换 active CSS 类。 通过设置 active 类的样式,可以让用户清楚地了解当前页面对应哪个导航链接。

使用 NavLink 时,主页链接示例如以下代码所示:

@page "/pizzas"
@inject NavigationManager NavManager

<h1>Buy a Pizza</h1>

<p>I want to order a: @PizzaName</p>

<NavLink href=@HomePageURI Match="NavLinkMatch.All">Home Page</NavLink>

@code {
	[Parameter]
	public string PizzaName { get; set; }
	
	public string HomePageURI { get; set; }
	
	protected override void OnInitialized()
	{
		HomePageURI = NavManager.BaseUri;
	}
}

NavLink 组件中的 Match 属性用于管理突出显示连接的时间。 有两个选项:

  • NavLinkMatch.All:使用此值时,只有在链接的 href 与当前 URL 完全匹配时,该链接才突出显示为活动链接。
  • NavLinkMatch.Prefix:使用此值时,当链接的 href 与当前 URL 的第一部分匹配时,该链接就突出显示为活动链接。 例如,假设你拥有链接 <NavLink href="pizzas" Match="NavLinkMatch.Prefix">。 当前 URL 为 http://www.contoso.com/pizzas 及该 URL 中的任意位置(例如 http://www.contoso.com/pizzas/formaggio)时,此链接将突出显示为活动链接。 此行为可帮助用户了解自己当前正在查看网站的哪一部分。

路由参数

 

在本模块的前面部分中,你已学习了如何使用用户请求的部分 URI 将请求路由到正确的组件。 你通常希望将 URI 的其他部分用作呈现的页面中的值。 例如,假设用户请求:

http://www.contoso.com/favoritepizza/hawaiian

使用 @page 指令,你已了解如何将此请求路由到组件,例如 FavoritePizza.razor 组件。 现在你要在组件中利用值“hawaiian”。 若要获取此值,可以将其声明为路由参数。

使用 @page 指令指定将作为路由参数传递给组件的 URI 部分。 在组件的代码中,你可以像获取组件参数的值一样获取路由参数的值:

@page "/FavoritePizzas/{favorite}"

<h1>Choose a Pizza</h1>

<p>Your favorite pizza is: @Favorite</p>

@code {
	[Parameter]
	public string Favorite { get; set; }
}

以上代码在 @page 指令中使用大括号来指定路由参数并为其命名

备注

组件参数是从父组件发送到子组件的值。 在父组件中,以子组件标记属性的形式指定组件参数值。 路由参数的指定方式不同。 它们作为 URI 的一部分指定。 Blazor 路由器在后台截获这些值,并将其作为组件值发送到组件,因此你可以以相同的方式访问它们。 路由参数不区分大小写,将转发给同名的组件参数。

 

可选路由参数

 

在以上示例中,{favorite} 参数是必需的。 若要使路由参数可选,请使用问号:

@page "/FavoritePizzas/{favorite?}"

<h1>Choose a Pizza</h1>

<p>Your favorite pizza is: @Favorite</p>

@code {
	[Parameter]
	public string Favorite { get; set; }
	
	protected override void OnInitialized()
	{
		Favorite ??= "Fiorentina";
	}
}

为可选参数设置默认值是很好的做法。 在以上示例中,Favorite 参数的默认值在 OnInitialized 方法中设置。

备注

当用户第一次请求页面时,OnInitialized 方法运行。 如果用户使用不同的路由参数请求同一页面,则该方法不会运行。 例如,如果希望用户从 http://www.contoso.com/favoritepizza/hawaiian 转到 http://www.contoso.com/favoritepizza,请改为在 OnParametersSet() 方法中设置默认值。

路由约束

在以上示例中,请求 URI http://www.contoso.com/favoritepizza/2 的结果将是一条无意义的消息“你喜欢的披萨是:2”。 在其他情况下,这样的类型不匹配可能会导致异常,并向用户显示错误。 请考虑为路由参数指定类型:

@page "/FavoritePizza/{preferredsize:int}"

<h1>Choose a Pizza</h1>

<p>Your favorite pizza size is: @FavoriteSize inches.</p>

@code {
	[Parameter]
	public int FavoriteSize { get; set; }
}

在此示例中,如果用户请求了 http://www.contoso.com/favoritepizza/margherita,则没有上述组件的匹配项。 因此,请求会路由到其他位置。 如果用户请求 http://www.contoso.com/favoritepizza/12,则会有一个路径匹配,该组件会显示消息“您最喜欢的披萨尺寸是:12英寸”。这种路由参数的一个特定类型称为“路由约束”。 可以在约束中使用其他这些类型:

约束 示例 匹配项示例
bool {vegan:bool} http://www.contoso.com/pizzas/true
datetime {birthdate:datetime} http://www.contoso.com/customers/1995-12-12
decimal {maxprice:decimal} http://www.contoso.com/pizzas/15.00
double {weight:double} http://www.contoso.com/pizzas/1.234
float {weight:float} http://www.contoso.com/pizzas/1.564
guid {pizza id:guid} http://www.contoso.com/pizzas/CD2C1638-1638-72D5-1638-DEADBEEF1638
long {totals ales:long} http://www.contoso.com/pizzas/568192454

设置捕获全部路由参数

 

请考虑本单元前面部分中介绍的以下组件:

@page "/FavoritePizza/{favorite}"

<h1>Choose a Pizza</h1>

<p>Your favorite pizza is: @Favorite</p>

@code {
	[Parameter]
	public string Favorite { get; set; }
}

现在,假设用户尝试通过请求 URI http://www.contoso.com/favoritepizza/margherita/hawaiian 来指定两个喜好。 页面将显示消息“你喜欢的披萨是:玛格丽特”,并忽略子文件夹“hawaiian”。 可以使用捕获全部路由参数来更改此行为,该参数捕获跨多个 URI 文件夹边界(正斜杠)的路径。 将星号 (*) 作为路由参数名称前缀,使路由参数捕获全部:

@page "/FavoritePizza/{*favorites}"

<h1>Choose a Pizza</h1>

<p>Your favorite pizzas are: @Favorites</p>

@code {
	[Parameter]
	public string Favorites { get; set; }
}

使用相同的请求 URI,页面现在会显示消息“你喜欢的披萨是:玛格丽特/夏威夷风味”。