ASP.NET Core Blazor 路由ASP.NET Core Blazor routing

作者:Luke LathamBy Luke Latham

在本文中,学习如何管理请求路由以及如何使用 NavLink 组件在 Blazor 应用中创建导航链接。In this article, learn how to manage request routing and how to use the NavLink component to create a navigation links in Blazor apps.

路由模板Route templates

通过 Router 组件可在 Blazor 应用中路由到 Razor 组件。The Router component enables routing to Razor components in a Blazor app. Router 组件在 Blazor 应用的 App 组件中使用。The Router component is used in the App component of Blazor apps.

App.razor:App.razor:

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

备注

随着 ASP.NET Core 5.0.1 的发布及任何附加 5.x 版本的推出,Router 组件包含 PreferExactMatches 参数(设置为 @true)。With the release of ASP.NET Core 5.0.1 and for any additional 5.x releases, the Router component includes the PreferExactMatches parameter set to @true. 有关详细信息,请参阅 从 ASP.NET Core 3.1 迁移到5。0For more information, see 从 ASP.NET Core 3.1 迁移到5。0.

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

编译带有 @page 指令的 Razor 组件 (.razor) 时,将为生成的组件类提供一个 RouteAttribute 来指定组件的路由模板。When a Razor component (.razor) with an @page directive is compiled, the generated component class is provided a RouteAttribute specifying the component's route template.

当应用启动时,将扫描指定为 路由器的 AppAssembly 的程序集,来收集具有 RouteAttribute 的应用组件的路由信息。When the app starts, the assembly specified as the Router's AppAssembly is scanned to gather route information for the app's components that have a RouteAttribute.

在运行时,RouteView 组件:At runtime, the RouteView component:

  • Router 接收 RouteData 以及所有路由参数。Receives the RouteData from the Router along with any route parameters.
  • 使用指定的组件的布局来呈现该组件,包括任何后续嵌套布局。Renders the specified component with its layout, including any further nested layouts.

对于没有使用 @layout 指令指定布局的组件,可选择使用布局类指定一个 DefaultLayout 参数。Optionally specify a DefaultLayout parameter with a layout class for components that don't specify a layout with the @layout directive. 框架的 Blazor 项目模板会指定 MainLayout 组件 (Shared/MainLayout.razor) 作为应用的默认布局。The framework's Blazor project templates specify the MainLayout component (Shared/MainLayout.razor) as the app's default layout. 有关布局的详细信息,请参阅 ASP.NET Core Blazor 布局For more information on layouts, see ASP.NET Core Blazor 布局.

组件支持使用多个 @page 指令的多个路由模板。Components support multiple route templates using multiple @page directives. 以下示例组件会对 /BlazorRoute/DifferentBlazorRoute 的请求进行加载。The following example component loads on requests for /BlazorRoute and /DifferentBlazorRoute.

Pages/BlazorRoute.razor:Pages/BlazorRoute.razor:

@page "/BlazorRoute"
@page "/DifferentBlazorRoute"

<h1>Blazor routing</h1>
@page "/BlazorRoute"
@page "/DifferentBlazorRoute"

<h1>Blazor routing</h1>

重要

若要正确解析 URL,应用必须在其 wwwroot/index.html 文件 (Blazor WebAssembly) 或 Pages/_Host.cshtml 文件 (Blazor Server) 中加入 <base> 标记,并在 href 属性中指定应用基路径。For URLs to resolve correctly, the app must include a <base> tag in its wwwroot/index.html file (Blazor WebAssembly) or Pages/_Host.cshtml file (Blazor Server) with the app base path specified in the href attribute. 有关详细信息,请参阅 托管和部署 ASP.NET Core BlazorFor more information, see 托管和部署 ASP.NET Core Blazor.

在找不到内容时提供自定义内容Provide custom content when content isn't found

如果找不到所请求路由的内容,则 Router 组件允许应用指定自定义内容。The Router component allows the app to specify custom content if content isn't found for the requested route.

App 组件中,在 Router 组件的 NotFound 模板中设置自定义内容。In the App component, set custom content in the Router component's NotFound template.

App.razor:App.razor:

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

备注

随着 ASP.NET Core 5.0.1 的发布及任何附加 5.x 版本的推出,Router 组件包含 PreferExactMatches 参数(设置为 @true)。With the release of ASP.NET Core 5.0.1 and for any additional 5.x releases, the Router component includes the PreferExactMatches parameter set to @true. 有关详细信息,请参阅 从 ASP.NET Core 3.1 迁移到5。0For more information, see 从 ASP.NET Core 3.1 迁移到5。0.

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

任意项都可用作 <NotFound> 标记的内容,例如其他交互式组件。Arbitrary items are supported as content of the <NotFound> tags, such as other interactive components. 若要将默认布局应用于 NotFound 内容,请参阅 ASP.NET Core Blazor 布局To apply a default layout to NotFound content, see ASP.NET Core Blazor 布局.

从多个程序集路由到组件Route to components from multiple assemblies

使用 AdditionalAssemblies 参数为 Router 组件指定搜索可路由组件时要考虑的其他程序集。Use the AdditionalAssemblies parameter to specify additional assemblies for the Router component to consider when searching for routable components. 除了指定至 AppAssembly 的程序集外,还会扫描其他程序集。Additional assemblies are scanned in addition to the assembly specified to AppAssembly. 在以下示例中,Component1 是在引用的组件类库中定义的可路由组件。In the following example, Component1 is a routable component defined in a referenced component class library. 以下 AdditionalAssemblies 示例为 Component1 提供路由支持。The following AdditionalAssemblies example results in routing support for Component1.

App.razor:App.razor:

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

备注

随着 ASP.NET Core 5.0.1 的发布及任何附加 5.x 版本的推出,Router 组件包含 PreferExactMatches 参数(设置为 @true)。With the release of ASP.NET Core 5.0.1 and for any additional 5.x releases, the Router component includes the PreferExactMatches parameter set to @true. 有关详细信息,请参阅 从 ASP.NET Core 3.1 迁移到5。0For more information, see 从 ASP.NET Core 3.1 迁移到5。0.

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

路由参数Route parameters

路由器使用路由参数以相同的名称填充相应的组件参数The router uses route parameters to populate the corresponding component parameters with the same name. 路由参数名不区分大小写。Route parameter names are case insensitive. 在下面的示例中,text 参数将路由段的值赋给组件的 Text 属性。In the following example, the text parameter assigns the value of the route segment to the component's Text property. /RouteParameter/amazing发出请求时,<h1> 标记内容呈现为 Blazor is amazing!When a request is made for /RouteParameter/amazing, the <h1> tag content is rendered as Blazor is amazing!.

Pages/RouteParameter.razor:Pages/RouteParameter.razor:

@page "/RouteParameter/{text}"

<h1>Blazor is @Text!</h1>

@code {
    [Parameter]
    public string Text { get; set; }
}
@page "/RouteParameter/{text}"

<h1>Blazor is @Text!</h1>

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

支持可选参数。Optional parameters are supported. 在下面的示例中,text 可选参数将 route 段的值赋给组件的 Text 属性。In the following example, the text optional parameter assigns the value of the route segment to the component's Text property. 如果该段不存在,则将 Text 的值设置为 fantasticIf the segment isn't present, the value of Text is set to fantastic.

Pages/RouteParameter.razor:Pages/RouteParameter.razor:

@page "/RouteParameter/{text?}"

<h1>Blazor is @Text!</h1>

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

    protected override void OnInitialized()
    {
        Text = Text ?? "fantastic";
    }
}

不支持可选参数。Optional parameters aren't supported. 在下述示例中,应用了两个 @page 指令In the following example, two @page directives are applied. 第一个指令允许导航到没有参数的组件。The first directive permits navigation to the component without a parameter. 第二个指令将 {text} 路由参数分配给组件的 Text 属性。The second directive assigns the {text} route parameter value to the component's Text property.

Pages/RouteParameter.razor:Pages/RouteParameter.razor:

@page "/RouteParameter"
@page "/RouteParameter/{text}"

<h1>Blazor is @Text!</h1>

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

    protected override void OnInitialized()
    {
        Text = Text ?? "fantastic";
    }
}

OnParametersSet 上还不是在 OnInitialized 上使用,以允许应用使用不同的可选参数值导航到同一组件。Use on OnParametersSet instead of OnInitialized to permit app navigation to the same component with a different optional parameter value. 根据上述示例,当用户应该能够从 /RouteParameter 导航到 /RouteParameter/amazing 或从 /RouteParameter/amazing 导航到 /RouteParameter 时使用 OnParametersSetBased on the preceding example, use OnParametersSet when the user should be able to navigate from /RouteParameter to /RouteParameter/amazing or from /RouteParameter/amazing to /RouteParameter:

protected override void OnParametersSet()
{
    Text = Text ?? "fantastic";
}

路由约束Route constraints

路由约束强制在路由段和组件之间进行类型匹配。A route constraint enforces type matching on a route segment to a component.

在以下示例中,到 User 组件的路由仅在以下情况下匹配:In the following example, the route to the User component only matches if:

  • 请求 URL 中存在 Id 路由段。An Id route segment is present in the request URL.
  • Id 段是一个整数 (int) 类型。The Id segment is an integer (int) type.

Pages/User.razor:Pages/User.razor:

@page "/user/{Id:int}"

<h1>User Id: @Id</h1>

@code {
    [Parameter]
    public int Id { get; set; }
}
@page "/user/{Id:int}"

<h1>User Id: @Id</h1>

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

下表中显示的路由约束可用。The route constraints shown in the following table are available. 有关与固定区域性匹配的路由约束,请参阅表下方的警告了解详细信息。For the route constraints that match the invariant culture, see the warning below the table for more information.

约束Constraint 示例Example 匹配项示例Example Matches 固定条件Invariant
区域性culture
匹配matching
bool {active:bool} true, FALSEtrue, FALSE No
datetime {dob:datetime} 2016-12-31, 2016-12-31 7:32pm2016-12-31, 2016-12-31 7:32pm Yes
decimal {price:decimal} 49.99, -1,000.0149.99, -1,000.01 Yes
double {weight:double} 1.234, -1,001.01e81.234, -1,001.01e8 Yes
float {weight:float} 1.234, -1,001.01e81.234, -1,001.01e8 Yes
guid {id:guid} CD2C1638-1638-72D5-1638-DEADBEEF1638, {CD2C1638-1638-72D5-1638-DEADBEEF1638}CD2C1638-1638-72D5-1638-DEADBEEF1638, {CD2C1638-1638-72D5-1638-DEADBEEF1638} No
int {id:int} 123456789, -123456789123456789, -123456789 Yes
long {ticks:long} 123456789, -123456789123456789, -123456789 Yes

警告

验证 URL 的路由约束并将转换为始终使用固定区域性的 CLR 类型(例如 intDateTime)。Route constraints that verify the URL and are converted to a CLR type (such as int or DateTime) always use the invariant culture. 这些约束假定 URL 不可本地化。These constraints assume that the URL is non-localizable.

使用包含点的 URL 进行路由Routing with URLs that contain dots

对于托管的 Blazor WebAssembly 和 Blazor Server应用,服务器端默认路由模板假定如果请求 URL 的最后一段包含一个点 (.),则请求一个文件。For hosted Blazor WebAssembly and Blazor Server apps, the server-side default route template assumes that if the last segment of a request URL contains a dot (.) that a file is requested. 例如,URL https://localhost.com:5001/example/some.thing 由路由器解释为名为 some.thing 的文件的请求。For example, the URL https://localhost.com:5001/example/some.thing is interpreted by the router as a request for a file named some.thing. 在没有额外配置的情况下,如果 some.thing 是指通过 @page 指令路由到一个组件,且 some.thing 是一个路由参数值,那么应用将返回“404 - 未找到”响应。Without additional configuration, an app returns a 404 - Not Found response if some.thing was meant to route to a component with an @page directive and some.thing is a route parameter value. 若要使用具有包含点的一个或多个参数的路由,则应用必须使用自定义模板配置该路由。To use a route with one or more parameters that contain a dot, the app must configure the route with a custom template.

请考虑下面的 Example 组件,它可以从 URL 的最后一段接收路由参数。Consider the following Example component that can receive a route parameter from the last segment of the URL.

Pages/Example.razor:Pages/Example.razor:

@page "/example/{param?}"

<p>
    Param: @Param
</p>

@code {
    [Parameter]
    public string Param { get; set; }
}
@page "/example"
@page "/example/{param}"

<p>
    Param: @Param
</p>

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

若要允许托管的 Blazor WebAssembly 解决方案的 Server 应用在 param 路由参数中使用一个点来路由请求,请添加一个回退文件路由模板,在该模板的 Startup.Configure 中包含该可选参数。To permit the Server app of a hosted Blazor WebAssembly solution to route the request with a dot in the param route parameter, add a fallback file route template with the optional parameter in Startup.Configure.

Startup.cs:Startup.cs:

endpoints.MapFallbackToFile("/example/{param?}", "index.html");

若要配置 Blazor Server应用,使其在 param 路由参数中使用一个点来路由请求,请添加一个回退页面路由模板,该模板具有Startup.Configure 中的可选参数。To configure a Blazor Server app to route the request with a dot in the param route parameter, add a fallback page route template with the optional parameter in Startup.Configure.

Startup.cs:Startup.cs:

endpoints.MapFallbackToPage("/example/{param?}", "/_Host");

有关详细信息,请参阅 ASP.NET Core 中的路由For more information, see ASP.NET Core 中的路由.

catch-all 路由参数Catch-all route parameters

组件支持可跨多个文件夹边界捕获路径的 catch-all 路由参数。Catch-all route parameters, which capture paths across multiple folder boundaries, are supported in components.

Catch-all 路由参数是:Catch-all route parameters are:

  • 以与路由段名称匹配的方式命名。Named to match the route segment name. 命名不区分大小写。Naming isn't case sensitive.
  • string 类型。A string type. 框架不提供自动强制转换。The framework doesn't provide automatic casting.
  • 位于 URL 的末尾。At the end of the URL.

Pages/CatchAll.razor:Pages/CatchAll.razor:

@page "/catch-all/{*pageRoute}"

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

对于具有 /catch-all/{*pageRoute} 路由模板的 URL /catch-all/this/is/a/testPageRoute 的值设置为 this/is/a/testFor the URL /catch-all/this/is/a/test with a route template of /catch-all/{*pageRoute}, the value of PageRoute is set to this/is/a/test.

对捕获路径的斜杠和段进行解码。Slashes and segments of the captured path are decoded. 对于 /catch-all/{*pageRoute} 的路由模板,URL /catch-all/this/is/a%2Ftest%2A 会生成 this/is/a/test*For a route template of /catch-all/{*pageRoute}, the URL /catch-all/this/is/a%2Ftest%2A yields this/is/a/test*.

ASP.NET Core 5.0 或更高版本中支持 catch-all 路由参数。Catch-all route parameters are supported in ASP.NET Core 5.0 or later. 有关详细信息,请选择本文的 5.0 版本。For more information, select the 5.0 version of this article.

URI 和导航状态帮助程序URI and navigation state helpers

在 C# 代码中使用 NavigationManager 来来管理 URI 和导航。Use NavigationManager to manage URIs and navigation in C# code. NavigationManager 提供下表所示的事件和方法。NavigationManager provides the event and methods shown in the following table.

成员Member 描述Description
Uri 获取当前绝对 URI。Gets the current absolute URI.
BaseUri 获取可在相对 URI 路径之前添加用于生成绝对 URI 的基 URI(带有尾部反斜杠)。Gets the base URI (with a trailing slash) that can be prepended to relative URI paths to produce an absolute URI. 通常,BaseUri 对应于 wwwroot/index.html (Blazor WebAssembly) 或 Pages/_Host.cshtml (Blazor Server) 中文档的 <base> 元素上的 href 属性。Typically, BaseUri corresponds to the href attribute on the document's <base> element in wwwroot/index.html (Blazor WebAssembly) or Pages/_Host.cshtml (Blazor Server).
NavigateTo 导航到指定 URI。Navigates to the specified URI. 如果 forceLoadtrue,则:If forceLoad is true:
  • 客户端路由会被绕过。Client-side routing is bypassed.
  • 无论 URI 是否通常由客户端路由器处理,浏览器都必须从服务器加载新页面。The browser is forced to load the new page from the server, whether or not the URI is normally handled by the client-side router.
LocationChanged 导航位置更改时触发的事件。An event that fires when the navigation location has changed.
ToAbsoluteUri 将相对 URI 转换为绝对 URI。Converts a relative URI into an absolute URI.
ToBaseRelativePath 给定基 URI(例如,之前由 BaseUri 返回的 URI),将绝对 URI 转换为相对于基 URI 前缀的 URI。Given a base URI (for example, a URI previously returned by BaseUri), converts an absolute URI into a URI relative to the base URI prefix.

对于 LocationChanged 事件,LocationChangedEventArgs 提供了下述导航事件信息:For the LocationChanged event, LocationChangedEventArgs provides the following information about navigation events:

以下组件:The following component:

  • 使用 NavigateTo 选择按钮后,导航到应用的 Counter 组件 (Pages/Counter.razor)。Navigates to the app's Counter component (Pages/Counter.razor) when the button is selected using NavigateTo.
  • 通过订阅 NavigationManager.LocationChanged 来处理位置更改事件。Handles the location changed event by subscribing to NavigationManager.LocationChanged.
    • 在框架调用 Dispose 时,解除挂接 HandleLocationChanged 方法。The HandleLocationChanged method is unhooked when Dispose is called by the framework. 解除挂接该方法可允许组件进行垃圾回收。Unhooking the method permits garbage collection of the component.

    • 选择该按钮时,记录器实现会记录以下信息:The logger implementation logs the following information when the button is selected:

      BlazorSample.Pages.Navigate: Information: URL of new location: https://localhost:5001/counter

Pages/Navigate.razor:Pages/Navigate.razor:

@page "/navigate"
@using Microsoft.Extensions.Logging 
@implements IDisposable
@inject NavigationManager NavigationManager
@inject ILogger<Navigate> Logger

<h1>Navigate in component code example</h1>

<button class="btn btn-primary" @onclick="NavigateToCounterComponent">
    Navigate to the Counter component
</button>

@code {
    private void NavigateToCounterComponent()
    {
        NavigationManager.NavigateTo("counter");
    }

    protected override void OnInitialized()
    {
        NavigationManager.LocationChanged += HandleLocationChanged;
    }

    private void HandleLocationChanged(object sender, LocationChangedEventArgs e)
    {
        Logger.LogInformation("URL of new location: {Location}", e.Location);
    }

    public void Dispose()
    {
        NavigationManager.LocationChanged -= HandleLocationChanged;
    }
}
@page "/navigate"
@using Microsoft.Extensions.Logging 
@implements IDisposable
@inject NavigationManager NavigationManager
@inject ILogger<Navigate> Logger

<h1>Navigate in component code example</h1>

<button class="btn btn-primary" @onclick="NavigateToCounterComponent">
    Navigate to the Counter component
</button>

@code {
    private void NavigateToCounterComponent()
    {
        NavigationManager.NavigateTo("counter");
    }

    protected override void OnInitialized()
    {
        NavigationManager.LocationChanged += HandleLocationChanged;
    }

    private void HandleLocationChanged(object sender, LocationChangedEventArgs e)
    {
        Logger.LogInformation("URL of new location: {Location}", e.Location);
    }

    public void Dispose()
    {
        NavigationManager.LocationChanged -= HandleLocationChanged;
    }
}

要详细了解组件处置,请参阅 ASP.NET Core Blazor 生命周期For more information on component disposal, see ASP.NET Core Blazor 生命周期.

查询字符串和分析参数Query string and parse parameters

可从 NavigationManager.Uri 属性中获取请求的查询字符串:The query string of a request is obtained from the NavigationManager.Uri property:

@inject NavigationManager NavigationManager

...

var query = new Uri(NavigationManager.Uri).Query;

若要分析查询字符串的参数,请执行以下操作:To parse a query string's parameters:

以下 ParseQueryString 组件示例会分析名为 ship 的查询字符串参数键。The following ParseQueryString component example parses a query string parameter key named ship. 例如,URL 查询字符串键值对 ?ship=Tardis 会捕获 queryValue 中的值 TardisFor example, the URL query string key-value pair ?ship=Tardis captures the value Tardis in queryValue. 对于下述示例,请使用 URL https://localhost:5001/parse-query-string?ship=Tardis 导航到应用。For the following example, navigate to the app with the URL https://localhost:5001/parse-query-string?ship=Tardis.

Pages/ParseQueryString.razor:Pages/ParseQueryString.razor:

@page "/parse-query-string"
@using Microsoft.AspNetCore.WebUtilities
@inject NavigationManager NavigationManager

<h1>Query string parse example</h1>

<p>queryValue: @queryValue</p>

@code {
    private string queryValue = "A query string for 'ship' isn't present.";

    protected override void OnInitialized()
    {
        var query = new Uri(NavigationManager.Uri).Query;

        if (QueryHelpers.ParseQuery(query).TryGetValue("ship", out var value))
        {
            queryValue = value;
        }
    }
}
@page "/parse-query-string"
@using Microsoft.AspNetCore.WebUtilities
@inject NavigationManager NavigationManager

<h1>Query string parse example</h1>

<p>queryValue: @queryValue</p>

@code {
    private string queryValue = "A query string for 'ship' isn't present.";

    protected override void OnInitialized()
    {
        var query = new Uri(NavigationManager.Uri).Query;

        if (QueryHelpers.ParseQuery(query).TryGetValue("ship", out var value))
        {
            queryValue = value;
        }
    }
}

创建导航链接时,请使用 NavLink 组件代替 HTML 超链接元素 (<a>)。Use a NavLink component in place of HTML hyperlink elements (<a>) when creating navigation links. NavLink 组件的行为方式类似于 <a> 元素,但它根据其 href 是否与当前 URL 匹配来切换 active CSS 类。A NavLink component behaves like an <a> element, except it toggles an active CSS class based on whether its href matches the current URL. active 类可帮助用户了解所显示导航链接中的哪个页面是活动页面。The active class helps a user understand which page is the active page among the navigation links displayed. 也可以选择将 CSS 类名分配到 NavLink.ActiveClass,以便在当前路由与 href 匹配时将自定义 CSS 类应用到呈现的链接。Optionally, assign a CSS class name to NavLink.ActiveClass to apply a custom CSS class to the rendered link when the current route matches the href.

以下 NavMenu 组件创建 Bootstrap 导航栏,该导航栏演示如何使用 NavLink 组件:The following NavMenu component creates a Bootstrap navigation bar that demonstrates how to use NavLink components:

<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="component" Match="NavLinkMatch.Prefix">
                <span class="oi oi-plus" aria-hidden="true"></span> Link Text
            </NavLink>
        </li>
    </ul>
</div>
<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="component" Match="NavLinkMatch.Prefix">
                <span class="oi oi-plus" aria-hidden="true"></span> Link Text
            </NavLink>
        </li>
    </ul>
</div>

备注

NavMenu 组件 (NavMenu.razor) 是在应用的 Shared 文件夹中提供的,而该文件夹是从 Blazor 项目模板生成的。The NavMenu component (NavMenu.razor) is provided in the Shared folder of an app generated from the Blazor project templates.

有两个 NavLinkMatch 选项可分配给 <NavLink> 元素的 Match 属性:There are two NavLinkMatch options that you can assign to the Match attribute of the <NavLink> element:

在前面的示例中,主页 NavLink href="" 与主页 URL 匹配,并且仅在应用的默认基路径 URL(例如,https://localhost:5001/)处接收 active CSS 类。In the preceding example, the Home NavLink href="" matches the home URL and only receives the active CSS class at the app's default base path URL (for example, https://localhost:5001/). 当用户访问带有 component 前缀的任何 URL(例如,https://localhost:5001/componenthttps://localhost:5001/component/another-segment)时,第二个 NavLink 接收 active 类。The second NavLink receives the active class when the user visits any URL with a component prefix (for example, https://localhost:5001/component and https://localhost:5001/component/another-segment).

其他 NavLink 组件属性会传递到呈现的定位标记。Additional NavLink component attributes are passed through to the rendered anchor tag. 在以下示例中,NavLink 组件包括 target 属性:In the following example, the NavLink component includes the target attribute:

<NavLink href="example-page" target="_blank">Example page</NavLink>

呈现以下 HTML 标记:The following HTML markup is rendered:

<a href="example-page" target="_blank">Example page</a>

警告

由于 Blazor 呈现子内容的方式,如果在 NavLink(子)组件的内容中使用递增循环变量,则在 for 循环内呈现 NavLink 组件需要本地索引变量:Due to the way that Blazor renders child content, rendering NavLink components inside a for loop requires a local index variable if the incrementing loop variable is used in the NavLink (child) component's content:

@for (int c = 0; c < 10; c++)
{
    var current = c;
    <li ...>
        <NavLink ... href="@c">
            <span ...></span> @current
        </NavLink>
    </li>
}

子内容中使用循环变量的任何子组件(而不仅仅是 NavLink 组件)都要求必须在此方案中使用索引变量。Using an index variable in this scenario is a requirement for any child component that uses a loop variable in its child content, not just the NavLink component.

或者,将 foreach 循环用于 Enumerable.RangeAlternatively, use a foreach loop with Enumerable.Range:

@foreach(var c in Enumerable.Range(0,10))
{
    <li ...>
        <NavLink ... href="@c">
            <span ...></span> @c
        </NavLink>
    </li>
}

ASP.NET Core 终结点路由集成ASP.NET Core endpoint routing integration

本部分仅适用于 Blazor Server应用。This section only applies to Blazor Server apps.

Blazor Server 已集成到 ASP.NET Core 终结点路由中。Blazor Server is integrated into ASP.NET Core Endpoint Routing. ASP.NET Core 应用配置为接受 Startup.Configure 中带有 MapBlazorHub 的交互式组件的传入连接。An ASP.NET Core app is configured to accept incoming connections for interactive components with MapBlazorHub in Startup.Configure.

Startup.cs:Startup.cs:

app.UseRouting();

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

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

典型的配置是将所有请求路由到 Razor 页面,该页面充当 Blazor Server应用的服务器端部分的主机。The typical configuration is to route all requests to a Razor page, which acts as the host for the server-side part of the Blazor Server app. 按照约定,主机页面通常在应用的 Pages 文件夹中被命名为 _Host.cshtmlBy convention, the host page is usually named _Host.cshtml in the Pages folder of the app.

主机文件中指定的路由称为 回退路由,因为它在路由匹配中以较低的优先级运行。The route specified in the host file is called a fallback route because it operates with a low priority in route matching. 其他路由不匹配时,会使用回退路由。The fallback route is used when other routes don't match. 这让应用能够使用其他控制器和页面,而不会干扰 Blazor Server应用中的组件路由。This allows the app to use other controllers and pages without interfering with component routing in the Blazor Server app.

若要了解如何为非根 URL 服务器托管配置 MapFallbackToPage,请参阅 托管和部署 ASP.NET Core BlazorFor information on configuring MapFallbackToPage for non-root URL server hosting, see 托管和部署 ASP.NET Core Blazor.