ASP.NET Core Blazor 布局ASP.NET Core Blazor layouts

本文内容

作者:Rainer StropekLuke Latham

有些应用元素(例如菜单、版权消息和公司徽标)通常是应用整体布局的一部分,并被应用中的每个组件使用。将这些元素的代码复制到应用的所有组件中并不是高效的方法 — 每当其中一个元素需要更新,每个组件都必须更新。此类复制难以维护,并会随时间推移导致内容不一致。布局可解决此问题。

从技术上讲,布局也是一个组件。布局在 Razor 模板或 C# 代码中定义,并可使用数据绑定依赖项注入和其他组件方案。

若要将组件转换为布局,该组件应:

  • 继承自 LayoutComponentBase,后者为布局内的呈现内容定义 Body 属性。
  • 使用 Razor 语法 @Body 在布局标记中指定呈现内容的位置。

以下代码示例显示布局组件 MainLayout.razor 的 Razor 模板。布局继承 LayoutComponentBase 并在导航栏和页脚之间设置 @Body

  1. @inherits LayoutComponentBase
  2. <header>
  3. <h1>Doctor Who&trade; Episode Database</h1>
  4. </header>
  5. <nav>
  6. <a href="masterlist">Master Episode List</a>
  7. <a href="search">Search</a>
  8. <a href="new">Add Episode</a>
  9. </nav>
  10. @Body
  11. <footer>
  12. @TrademarkMessage
  13. </footer>
  14. @code {
  15. public string TrademarkMessage { get; set; } =
  16. "Doctor Who is a registered trademark of the BBC. " +
  17. "https://www.doctorwho.tv/";
  18. }

在基于其中一个 Blazor 应用模板的应用中,MainLayout 组件 (MainLayout.razor) 位于应用的 Shared 文件夹中。

默认布局Default layout

在应用的 App.razor 文件的 Router 组件中指定默认应用布局。默认 Blazor 模板提供的以下 Router 组件将默认布局设置为 MainLayout 组件:

  1. <Router AppAssembly="typeof(Startup).Assembly">
  2. <Found Context="routeData">
  3. <RouteView RouteData="@routeData" DefaultLayout="@typeof(MainLayout)" />
  4. </Found>
  5. <NotFound>
  6. <p>Sorry, there's nothing at this address.</p>
  7. </NotFound>
  8. </Router>

若要为 NotFound 内容提供默认布局,请为 NotFound 内容指定 LayoutView

  1. <Router AppAssembly="typeof(Startup).Assembly">
  2. <Found Context="routeData">
  3. <RouteView RouteData="@routeData" DefaultLayout="@typeof(MainLayout)" />
  4. </Found>
  5. <NotFound>
  6. <LayoutView Layout="typeof(MainLayout)">
  7. <h1>Page not found</h1>
  8. <p>Sorry, there's nothing at this address.</p>
  9. </LayoutView>
  10. </NotFound>
  11. </Router>

有关 Router 组件的详细信息,请参阅 ASP.NET Core Blazor 路由

在路由器中将布局指定为默认布局是一种有用的做法,因为可以按组件或按文件夹进行替代。最好使用路由器来设置应用的默认布局,因为这是最常规的方法。

在组件中指定布局Specify a layout in a component

使用 Razor 指令 @layout 将布局应用于组件。编译器将 @layout 转换为 LayoutAttribute,后者应用于组件类。

以下 MasterList 组件的内容插入到 MasterLayout@Body 的位置:

  1. @layout MasterLayout
  2. @page "/masterlist"
  3. <h1>Master Episode List</h1>

直接在组件中指定布局会替代路由器中设置的默认布局或从 _Imports.razor 导入的 @layout 指令。

集中式布局选择Centralized layout selection

应用的每个文件夹都可以选择包含名为 Imports.razor_ 的模板文件。编译器将导入文件中指定的指令包括在同一文件夹中的所有 Razor 模板内,并在其所有子文件夹中以递归方式包括。因此,包含 @layout MyCoolLayoutImports.razor 文件可确保文件夹中的所有组件都使用 MyCoolLayout无需将 @layout MyCoolLayout 重复添加到文件夹和子文件夹内的所有 .razor_ 文件。@using 指令也以相同的方式应用于组件。

以下 _Imports.razor 文件导入:

  • MyCoolLayout
  • 同一文件夹以及任何子文件夹中的所有 Razor 组件。
  • BlazorApp1.Data 命名空间。
  1. @layout MyCoolLayout
  2. @using Microsoft.AspNetCore.Components
  3. @using BlazorApp1.Data

_Imports.razor 文件类似于 Razor 视图和页面的 _ViewImports.cshtml 文件,但专门应用于 Razor 组件文件。

_Imports.razor 中指定布局会替代指定为路由器默认布局的布局。

嵌套布局Nested layouts

应用可以包含嵌套布局。组件可以引用一个布局,该布局反过来引用另一个布局。例如,嵌套布局用于创建多级菜单结构。

以下示例演示如何使用嵌套布局。EpisodesComponent.razor 文件是要显示的组件。该组件引用 MasterListLayout

  1. @layout MasterListLayout
  2. @page "/masterlist/episodes"
  3. <h1>Episodes</h1>

MasterListLayout.razor 文件提供 MasterListLayout该布局引用另一个布局 MasterLayout 并在其中呈现。EpisodesComponent 在显示 @Body 的位置呈现:

  1. @layout MasterLayout
  2. @inherits LayoutComponentBase
  3. <nav>
  4. <!-- Menu structure of master list -->
  5. ...
  6. </nav>
  7. @Body

最后,MasterLayout.razor 中的 MasterLayout 包含顶级布局元素,例如页眉、主菜单和页脚。具有 EpisodesComponentMasterListLayout@Body 显示的位置呈现:

  1. @inherits LayoutComponentBase
  2. <header>...</header>
  3. <nav>...</nav>
  4. @Body
  5. <footer>
  6. @TrademarkMessage
  7. </footer>
  8. @code {
  9. public string TrademarkMessage { get; set; } =
  10. "Doctor Who is a registered trademark of the BBC. " +
  11. "https://www.doctorwho.tv/";
  12. }

与集成组件共享 Razor Pages 布局Share a Razor Pages layout with integrated components

当可路由组件集成到 Razor Pages 应用中时,该应用的共享布局可与这些组件配合使用。有关详细信息,请参阅 将 ASP.NET Core Razor 组件集成到 Razor Pages 和 MVC 应用

其他资源Additional resources