翻译自 Waqas Anwar 2021年4月2日的文章 《A Developer’s Guide To Blazor Routing and Navigation》 [1]

检查传入的请求 URL 并将它们导航到对应的视图或页面是每个单页应用程序 (SPA) 框架的基本功能。Blazor Server 和 WebAssembly 应用程序也同样支持使用一些内置组件和服务进行路由。在本教程中,我将向您介绍在 Blazor 应用程序中实现路由所需了解的所有内容。

Blazor 应用程序中的路由配置

在开始为不同的 Blazor 组件/页面创建路由之前,我们需要了解如何将 Blazor Server 应用程序集成到 ASP.NET Core Endpoint 路由中。Blazor Server 应用程序通过 SignalR 连接与客户端进行通信,为了接受 Blazor 组件传入的连接,我们在 Startup.cs 文件的 Configure 方法中调用了 MapBlazorHub 方法,如下所示:

app.UseEndpoints(endpoints =>
{endpoints.MapBlazorHub();endpoints.MapFallbackToPage("/_Host");
});

默认配置将所有请求都转发到一个 Razor 页面,该页面扮演 Blazor Server 应用程序服务端主机的角色。按照惯例,该主页是 _Host.cshtml,它位于应用程序的 Pages 文件夹中。该主文件中指定的路由称之为应急路由,在路由匹配中具有极低的优先级,这意味着当没有其他路由匹配时,才会使用该路由。

Blazor 路由组件介绍

Router[2] 组件是 Blazor 中的内置组件之一,用在 Blazor 应用程序的 App 组件之中。该组件启用了 Blazor 应用程序中的路由,并提供与当前导航状态相对应的路由数据。它拦截传入的请求并呈现与请求 URL 相匹配的页面。

<Router AppAssembly="@typeof(Program).Assembly" PreferExactMatches="@true"><Found Context="routeData"><RouteView RouteData="@routeData" DefaultLayout="@typeof(MainLayout)" /></Found><NotFound><LayoutView Layout="@typeof(MainLayout)"><p>Sorry, there's nothing at this address.</p></LayoutView></NotFound>
</Router>

下表显示了 Router 组件的属性。

当编译 Blazor 组件 (.razor) 时,它们生成的 C# 类会保存在 obj\Debug\net5.0\Razor\Pages 文件夹中。

如果您打开任意一个已编译的文件,将会注意到在编译之后,所有带有 @page 指令的组件都生成了一个带有 RouteAttribute 特性的类。

当应用程序启动时,会扫描通过 AppAssembly 属性指定的程序集,从所有指定了 RouteAttribute 特性的类中收集路由信息。

<Router AppAssembly="@typeof(Program).Assembly" PreferExactMatches="@true">

如果您创建了独立的组件类库,并希望应用程序从这些程序集中扫描和加载路由,那么您可以使用 AdditionalAssemblies 属性来接受一个 Assembly 对象集合。

下面是一个从定义在组件类库中的两个可路由组件(Component1 和 Component2)加载路由信息的示例。

<Router AppAssembly="@typeof(Program).Assembly" PreferExactMatches="@true"AdditionalAssemblies="new[] { typeof(Component1).Assembly, typeof(Component2).Assembly }">
</Router>

在运行时,RouteView 组件从 Router 接收 RouteData 以及任意路由参数,并使用组件中定义的布局渲染指定的组件。如果未定义布局,则使用 DefaultLayout 属性指定的布局。默认的布局通常是 Shared 文件夹中的 MainLayout 组件,不过您也可以创建并指定一个自定义布局。

<RouteView RouteData="@routeData" DefaultLayout="@typeof(MainLayout)" />

Found 模板用于在找到匹配的路由时显示其内容,正如您在下图中所看到的那样,其中找到了一个匹配路由,并在浏览器中呈现了一个 Counter 页面。

NotFound 模板用于在没有找到匹配的路由时显示内容。默认情况下,NotFound 模板仅显示一条消息,如下面的截图所示。

我们还可以创建自定义错误的布局和页面,以显示自定义错误页面。让我们在 Shared 文件夹中创建一个新的名为 ErrorLayout.razor 的自定义布局。

ErrorLayout.razor

@inherits LayoutComponentBase<main role="main" class="container"> <div class="text-center">@Body</div>
</main>

然后将 LayoutView 组件的 Layout 属性改为 ErrorLayout,并将 LayoutView 里的内容修改如下:

<Router AppAssembly="@typeof(Program).Assembly" PreferExactMatches="@true"><Found Context="routeData"><RouteView RouteData="@routeData" DefaultLayout="@typeof(MainLayout)" /></Found><NotFound><LayoutView Layout="@typeof(ErrorLayout)"><h1 class="display-1">404</h1><h1 class="display-4">Not Found</h1><p class="lead">Oops! Looks like this page doesn't exist.</p></LayoutView></NotFound>
</Router>

现在,如果您在浏览器中运行应用程序,并尝试访问一个未在应用中任何位置指定过的 URL,那么您将会看到一个自定义的 404 错误页面,如下所示。

所有 Blazor 应用程序都应将 PreferExactMatches 特性显式地设置为 @true,以便路由匹配更倾向于精确匹配,而不是通配符匹配。根据 Microsoft 官方文档,此特性从 .NET 6 开始将不可用,路由器将总是更倾向于精确匹配。

定义路由、参数和约束

在我们学习如何为 Blazor 组件定义路由之前,我们需要确保下面的 base 标签在每个页面都可用,以便正确地解析 URL。如果创建的是 Blazor Server 应用程序,那么您可以将此标签添加到 Pages/_Host.cshtml 文件的 head 部分,如果是 Blazor WebAssembly 应用程序,则可以将此标签添加到 wwwroot/index.html 文件中。

<base href="~/" />

要定义路由,我们可以使用 @page 指令,如下面的 Counter 组件示例所示。

@page "/counter"<h1>Counter</h1><p>Current count: @currentCount</p><button class="btn btn-primary" @onclick="IncrementCount">Click me</button>@code {private int currentCount = 0;private void IncrementCount(){currentCount++;}
}

现在我们就可以使用 /counter URL 访问 Counter 组件了。

我们还可以使用多个 @page 指令定义多个路由模板,如下面例所示。

@page "/counter"
@page "/mycounter"

这意味着现在也可以使用 /mycounter URL 访问同一个 Counter 组件:

使用路由参数将数据从一个页面传递到另一个页面是十分常见的做法,Blazor 路由模板支持路由参数。路由参数名称不区分大小写,一旦我们定义了路由参数,路由器就会自动填充对应的具有相同名称的组件属性。例如,在下面的代码片段中,我们在组件中定义了一个路由参数 title,并创建了一个对应的属性 Title。此属性将自动使用路由参数文本的值填充。然后,我们在 h1 元素中显示 Title 属性作为页面的标题。

@page "/counter/{title}"<h1>@Title</h1><p>Current count: @currentCount</p><button class="btn btn-primary" @onclick="IncrementCount">Click me</button>@code {private int currentCount = 0;[Parameter]public string Title { get; set; }private void IncrementCount(){currentCount++;}
}

运行应用程序,并尝试在地址栏中 /counter/ 之后指定任意的字符串,您将看到路由参数的值会显示为页面标题。

我们还可以定义可选的路由参数,如下例所示,其中 title 是可选参数,因为在此参数名称后面带有问号 (?)。假如我们不提供此路由参数的值,该参数将在 OnInitialized 方法中使用默认值 Counter 进行初始化。

@page "/counter/{title?}"<h1>@Title</h1><p>Current count: @currentCount</p><button class="btn btn-primary" @onclick="IncrementCount">Click me</button>@code {private int currentCount = 0;[Parameter]public string Title { get; set; }protected override void OnInitialized(){Title = Title ?? "Counter";}private void IncrementCount(){currentCount++;}
}

Blazor 还支持路由约束,在路由上强制类型匹配。在下面的代码片段中,我创建了一个 int 类型的路由参数 start,这意味着现在我只能为此路由参数提供整数值。计数器现在将以路由参数中指定的值开始计数。

@page "/counter/{start:int}"<h1>Counter</h1><p>Current count: @Start</p><button class="btn btn-primary" @onclick="IncrementCount">Click me</button>@code { [Parameter]public int Start { get; set; }private void IncrementCount(){Start++;}
}

在浏览器中运行应用程序,并在 URL 中指定任一整数值,比如 /counter/4,您会看到计数器将以该起始值递增。

下表显示了 Blazor 路由约束支持的类型。

还可以定义多个路由参数,如下例所示,我们将 start 和 increment 定义为 int 类型的参数。

@page "/counter/{start:int}/{increment:int}"<h1>Counter</h1><p>Current count: @Start</p><button class="btn btn-primary" @onclick="IncrementCount">Click me</button>@code { [Parameter]public int Start { get; set; }[Parameter]public int Increment { get; set; }private void IncrementCount(){Start+=Increment;}
}

如下所示,运行应用程序并在 URL 地址中指定 start 和 increment 的值,您会注意到,当您每次点击 Click me 按钮时,计数器不仅会以数字 2 开始计数,而且会以 3 递增。

Blazor NavigationManager 服务概述

NavigationManager 服务允许我们在 C# 代码中管理 URI 和导航。NavigationManager 类具有以下常见的属性、方法和事件。

让我们来创建一个页面,查看一下以上属性和方法的一些实际行为。创建一个新的 Blazor 组件并使用 @inject 指令注入 NavigationManager 服务。尝试在页面上打印出 Uri 和 BaseUri 属性,来查看一下它们返回的是什么类型的 URI。

@page "/navigationmanager"
@inject NavigationManager nvm<h3>Navigation Manager</h3>
<br /><p>@nvm.Uri</p>
<p>@nvm.BaseUri</p>

运行应用程序,您将在浏览器中看到类似以下内容的输出。Uri 属性显示当前页面的绝对 URI,而 BaseUri 属性显示当前的基 URI。

在页面上添加两个按钮 Home Page 和 Counter Page,并在 @code 代码块中添加它们的 onclick 事件处理方法。在事件处理方法中,我们可以在 C# 代码中使用 NavigateTo 方法将用户重定向到其它的 Blazor 组件。

@page "/navigationmanager"
@inject NavigationManager nvm<h3>Navigation Manager</h3>
<br /><p>@nvm.Uri</p>
<p>@nvm.BaseUri</p><button class="btn btn-primary" @onclick="GoToHome">Home Page
</button><button class="btn btn-primary" @onclick="GoToCounter">Counter Page
</button>@code {private void GoToHome(){nvm.NavigateTo("/");}private void GoToCounter(){nvm.NavigateTo("counter");}
}

运行应用程序并试着点击这两个按钮,将按预期的那样,您可以导航到主页和计数器页面。

如果不想以编程方式处理导航,而想在 HTML 中生成超链接,则可以使用 Blazor NavLink 组件。NavLink 组件类似于 HTML 中的 <a> 元素,具有一些很酷的功能。如果 NavLink 的 href 特性值与当前的 URL 相匹配,则会自动切换该元素的 active CSS 类(class)。这就使得我们可以在当前选中的链接上应用不同的样式。您可以在 Shared/NavMenu.razor 文件中看到这个组件的用法。

<div class="@NavMenuCssClass" @onclick="ToggleNavMenu"><ul class="nav flex-column"><li class="nav-item px-3"><NavLink class="nav-link" href="" Match="NavLinkMatch.All"><span class="oi oi-home" aria-hidden="true"></span> Home</NavLink></li><li class="nav-item px-3"><NavLink class="nav-link" href="counter"><span class="oi oi-plus" aria-hidden="true"></span> Counter</NavLink></li><li class="nav-item px-3"><NavLink class="nav-link" href="fetchdata"><span class="oi oi-list-rich" aria-hidden="true"></span> Fetch data</NavLink></li> </ul>
</div>

NavLink 组件还有一个 Match 属性,可以设置为以下选项之一:

  • NavLinkMatch.All:指定当 NavLink 与整个当前 URL 匹配时应处于活动状态。

  • NavLinkMatch.Prefix(默认值):指定当 NavLink 与当前 URL 的任意前缀匹配时应处于活动状态。

Match 属性:获取或设置一个值,该值表示 URL 匹配行为。

总结

在本教程中,我尝试介绍 Blazor 应用程序中的多种路由功能,还介绍了开发者可用的与路由相关的一些组件和服务。我希望您现在能够更熟练地定义路由、参数和约束。如果您喜欢本教程,请与他人分享以传播知识。

相关阅读:

  • Blazor Server 和 WebAssembly 应用程序入门指南

  • Blazor 组件入门指南

  • Blazor 数据绑定开发指南

  • Blazor 事件处理开发指南

  • Blazor 组件之间使用 EventCallback 进行通信

  • Blazor 路由及导航开发指南(本文)


相关链接:

  1. https://www.ezzylearning.net/tutorial/a-developers-guide-to-blazor-routing-and-navigation A Developer’s Guide To Blazor Routing and Navigation ↩︎

  2. https://docs.microsoft.com/zh-cn/dotnet/api/microsoft.aspnetcore.components.routing.router ↩︎

作者 :Waqas Anwar
译者 :技术译民
出品 :技术译站(https://ITTranslator.cn/)

Blazor 路由及导航开发指南相关推荐

  1. Blazor 模板化组件开发指南

    翻译自 Waqas Anwar 2021年4月15日的文章 <A Developer's Guide To Blazor Templated Components> [1] 在我之前的一篇 ...

  2. iOS内置地图导航开发指南

    0.起步 项目版本有内置地图的开发需求,因此做了一波技术预研. 0.1 MapKit MapKit是苹果的内置地图框架,目前在国内使用的是高德地图提供的服务,所以即便是内置地图,也能提供较为详细的地图 ...

  3. 高德地图android 测试,平行路检测-专业导航-开发指南-Android 导航SDK | 高德地图API...

    基本介绍 导航SDK从v6.6.0开始,平行路检测支持"主辅路状态检测"和"高架桥上下状态检测".当用户所在的位置,具有两条相邻的平行路,如城市快速路的主干道和 ...

  4. Blazor 组件库开发指南

    翻译自 Waqas Anwar 2021年5月21日的文章 <A Developer's Guide To Blazor Component Libraries> [1] Blazor 的 ...

  5. Blazor 事件处理开发指南

    翻译自 Waqas Anwar 2021年3月25日的文章 <A Developer's Guide To Blazor Event Handling> [1] 如果您正在开发交互式 We ...

  6. Blazor 数据绑定开发指南

    翻译自 Waqas Anwar 2021年3月21日的文章 <A Developer's Guide to Blazor Data Binding> [1] 现如今,大多数 Web 应用程 ...

  7. OpenWrt开发指南博文导航

    自博主更新该专栏也很久了,今天博主就给出关于OpenWrt开发的一个导航,为的是读者朋友能更好找到自己所感兴趣的那一块,当然博主以后对OpenWrt有新的发现和想法也会在第一时间发表在CSDN上,在此 ...

  8. android开发导航sdk,Android导航SDK开发指南(26页)-原创力文档

    Android 导航SDK 开发指南 一.概述 Android 导航SDK 目前为V1.1 版本,以.jar 形式提供,请广大开发者使用SDK 前务必 在官网申请key,以便全部功能顺利使用. And ...

  9. 《游戏AI开发指南(基于Lua的人工智能在游戏中的应用)》(Yanlz+Unity+SteamVR+5G+AI+VR云游戏+Lua+人机交互+沙箱+导航+决策树+影响力地图+立钻哥哥+==)

    <游戏AI开发指南(基于Lua的人工智能在游戏中的应用)> <游戏AI开发指南(基于Lua的人工智能在游戏中的应用)> 版本 作者 参与者 完成日期 备注 YanlzAI_Lu ...

最新文章

  1. Blender多米诺骨牌动画学习教程 The Impossible Domino Run in Blender
  2. 关系型数据库之Mysql备份(五)
  3. git编辑器选哪个_对比了3款markdown编辑器,哪一款适合你呢?来看看吧
  4. 树莓派 4B安装ubuntu18.04与melodic版ROS
  5. oracle备份还原到本地_Oracle 11g R2 RAC数据库备份通过RMAN恢复到单实例数据库实现...
  6. 06_特征选择,特征选择的原因,sklearn特征选择API
  7. SSL certificate problem: unable to get local issuer certificate 的解决方法
  8. android开发 交换方向,Android实现去哪儿携程地址互换效果
  9. mysql limit的使用方法
  10. js禁止鼠标滑轮_js实现鼠标滑动到某个div禁止滚动
  11. date.gethour_Java LocalDateTime类| 带示例的getHour()方法
  12. js字符串的字典序_27. 字符串的排列
  13. [Linux 性能检测工具]SAR
  14. 【多任务】多任务学习在推荐算法中的应用
  15. 《DSP using MATLAB》Problem 7.25
  16. [iOS] 通知详解: iOS 10 UserNotifications -- 附加包Media Attachments
  17. 数字图像处理的技术方法和应用
  18. NUC搭建Centos8服务器
  19. veracrypt取消加密卷_VeraCrypt 加密个人隐私(便携式 )
  20. Python-Flask实战项目一:仿知乎轻量级web问答平台搭建

热门文章

  1. EIGRP stub SIA
  2. 复习一下日志等级类型
  3. php curl_init函数用法
  4. 一起谈.NET技术,异步调用与多线程的区别
  5. 重构的小故事 Change Value to Reference or Vice Verse
  6. Oracle树形结构查询之prior的理解
  7. CodeChef Chef and Churu [分块]
  8. nginx获得response自定义的header
  9. 使用PowerShell配置Microsoft Teams
  10. Android添加item动画,RecyclerView基础篇-Item添加动画