Blazor之路由

路由的常用场景

Web开发当中,路由是指页面之间的相互跳转,最常见的有以下两种情况:

  • 浏览器输入地址或者点击链接
  • 业务代码的定向跳转

不管通过哪种方式,其实本质上都是一样的,都是通过URL的来定位到对应的页面。
这里还是以WebAssembly的项目为基础来探索一下路由的功能吧。对项目结构不清楚的朋友可以先看上一篇Blazor 初体验。

浏览器输入地址或者点击链接

通过上一篇Blazor 初体验我们已经知道每个页面都有个@page指令来定义该页面对应的URL。 比如:

@page "/"
@page "/counter"
@page "/fetchdata"

这样页面和URL之间就有了对应关系(可以称之为路由表)。那如果我们输入的地址找不到对应的页面会发生什么情况呢?
笔者特意试了一下,输入http://localhost:5000/unkonw, 结果是这样的:
Blazor之路由_第1张图片

在此有必要再回顾一下App.razor页面:

<Router AppAssembly="@typeof(Program).Assembly">
    <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>

她分别定义了Found和NotFound两个节点,
Found节点包含一个RouteView的定义,如果找到了路由定义就通过RouteView来呈现对应的页面,同时她还可以为所有页面指定默认的模板。按理说应该也可以在每个页面单独设置模板(同MVC一样),不过暂时还没试,留待之后研究。
NotFound节点包含一个LayoutView的定义,如果没找到路由定义则通过她来呈现一个特定的页面(可以说是自定义404页面),注意这里也使用了模板,而且和Found里面的是同一个,实际项目当中应该很多情况都是将Found和NotFound的模板分开的,当然这里也可以不指定模板。

业务代码的定向跳转

除了输入URL或者点击链接跳转(主动跳转),很多时候需要根据业务需要跳转到不同的页面(被动跳转),类似于WebForm的Response.Redirect方法或者MVC里面的RedirectToAction。
Blazor要处理这种逻辑,需要引入NavigationManager类(在Microsoft.AspNetCore.Components命名空间下),简单修改一下index.razor文件即可演示需要的效果:

@page "/"
@inject NavigationManager navigationManager
<h1>Hello, world!h1>

Welcome to your new app.

<SurveyPrompt Title="How is Blazor working for you?" />

<button class="btn btn-primary" @onclick="DirectToCounter1">
    Navigate to the Counter Page 1
button>
<button class="btn btn-primary" @onclick="DirectToCounter2">
    Navigate to the Counter Page 2
button>
<button class="btn btn-primary" @onclick="DirectToCounter3">
    Navigate to the Counter Page 3
button>
<button class="btn btn-primary" @onclick="DirectToCounter4">
    Navigate to the Counter Page 4
button>
@code {
    private void DirectToCounter1()
    {
        navigationManager.NavigateTo("../counter");
    }

    private void DirectToCounter2()
    {
        navigationManager.NavigateTo("./counter");
    }

    private void DirectToCounter3()
    {
        navigationManager.NavigateTo("/counter");
    }

    private void DirectToCounter4()
    {
        navigationManager.NavigateTo("counter");
    }
}

这里笔者试了NavigateTo的4种不同的参数,发现结果都是一样的,根本就没有相对路径的事,而且用a标签的href属性也是一样的结果,如果是这样的话,那笔者更倾向于第三种,跟路由定义里面的保持一致。

这里的navigationManager不仅提供跳转的功能,她还有一个LocationChanged事件,在跳转URL的时候触发,可以帮助我们丰富自己的应用。

路由参数

路由的过程当中经常需要用到参数,比如从列表页跳转到详情页就需要把id传过去,那么我们应该如何取到该参数的值呢,请看以下代码:

@page "/users/{id}"

<h1>User @Idh1>

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

}

首先用@page指令定义路由,声明变量{id}, 然后在code里面声明属性Id,并用Parameter修饰即可。
注意这里是不区分大小写的,但是为了更规范,建议URL全部用小写,c#代码则使用驼峰式命名。
还有blazor并不支持可选(Optional)参数,所以如果这个例子里面的id是可有可无的话,则需要使用@page指令来定义两条路由,一条包含id,另一条不包含。

同MVC一样,这里的参数也是支持约束的,比如你可以声明为{id:int}来只匹配整数参数, 目前支持以下几种约束类型:

  • bool
  • datetime
  • decimal
  • double
  • float
  • guid
  • int
  • long

还有一种常见的参数类型就是查询字符串QueryString,官方文档没有介绍这种情况,下次研究一下。

路由控件NavLink

NavLink其实就是一个链接,但她提供了一个额外的功能,就是当前地址与链接地址匹配的时候,会给该链接增加一个名为active的样式名。
比如NavMenu.razor的代码:

<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>

这样我们就可以根据地址来高亮显示当前的链接了。
NavLink有个Match属性,可以选择完全匹配或者前缀匹配,默认为前缀匹配。上面的代码中,Home链接就是使用的完全匹配。

备忘

  • 如何在每个页面单独定义模板
  • 如果动态加载模板
  • 查询字符串如何取值
  • 路由事件及应用

你可能感兴趣的:(Blazor)