Макеты Blazor в ASP.NET CoreASP.NET Core Blazor layouts

Авторы: Райнер Стропек (Rainer Stropek) и Люк Латэм (Luke Latham)By Rainer Stropek and Luke Latham

Некоторые элементы приложения, такие как меню, сообщения об авторских правах и логотипы компании, обычно являются частью общего макета приложения и используются каждым компонентом в приложении.Some app elements, such as menus, copyright messages, and company logos, are usually part of app's overall layout and used by every component in the app. Копирование кода этих элементов во все компоненты приложения не является эффективным подходом.Copying the code of these elements into all of the components of an app isn't an efficient approach. Каждый раз, когда одному из элементов требуется обновление, нужно обновлять каждый компонент.Every time one of the elements requires an update, every component must be updated. Такое дублирование сложно поддерживать, и это может привести к несогласованному содержимому с течением времени.Such duplication is difficult to maintain and can lead to inconsistent content over time. Для решения этой проблемы используются макеты.Layouts solve this problem.

Технически макет представляет собой просто другой компонент.Technically, a layout is just another component. Макет определяется в шаблоне Razor или в коде C# и может использовать привязки данных, внедрения зависимостей и другие сценарии компонентов.A layout is defined in a Razor template or in C# code and can use data binding, dependency injection, and other component scenarios.

Чтобы превратить компонент в макет , компонент:To turn a component into a layout , the component:

  • Наследует от LayoutComponentBase, который определяет свойство Body для отображаемого содержимого внутри макета.Inherits from LayoutComponentBase, which defines a Body property for the rendered content inside the layout.
  • Использует синтаксис @Body Razor для указания расположения в разметке макета, в которой отображается содержимое.Uses the Razor syntax @Body to specify the location in the layout markup where the content is rendered.

В следующем примере кода показан шаблон Razor компонента макета MainLayout.razor.The following code sample shows the Razor template of a layout component, MainLayout.razor. Макет наследует LayoutComponentBase и задает @Body между панелью навигации и нижним колонтитулом:The layout inherits LayoutComponentBase and sets the @Body between the navigation bar and the footer:

@inherits LayoutComponentBase

<header>
    <h1>Doctor Who&trade; Episode Database</h1>
</header>

<nav>
    <a href="masterlist">Master Episode List</a>
    <a href="search">Search</a>
    <a href="new">Add Episode</a>
</nav>

@Body

<footer>
    @TrademarkMessage
</footer>

@code {
    public string TrademarkMessage { get; set; } = 
        "Doctor Who is a registered trademark of the BBC. " +
        "https://www.doctorwho.tv/";
}

MainLayoutMainLayout component

В приложении на основе одного из шаблонов проектов Blazor компонент MainLayout (MainLayout.razor) находится в папке Shared приложения:In an app based on one of the Blazor project templates, the MainLayout component (MainLayout.razor) is in the app's Shared folder:

@inherits LayoutComponentBase

<div class="page">
    <div class="sidebar">
        <NavMenu />
    </div>

    <div class="main">
        <div class="content px-4">
            @Body
        </div>
    </div>
</div>
@inherits LayoutComponentBase

<div class="sidebar">
    <NavMenu />
</div>

<div class="main">
    <div class="content px-4">
        @Body
    </div>
</div>

Макет по умолчаниюDefault layout

Укажите макет приложения по умолчанию в компоненте Router в файле App.razor приложения.Specify the default app layout in the Router component in the app's App.razor file. Следующий компонент Router, предоставляемый шаблонами Blazor по умолчанию, задает для макета по умолчанию компонент MainLayout:The following Router component, which is provided by the default Blazor templates, sets the default layout to the MainLayout component:

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

Чтобы предоставить макет по умолчанию для содержимого NotFound, укажите LayoutView для содержимого NotFound:To supply a default layout for NotFound content, specify a LayoutView for NotFound content:

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

Дополнительные сведения о компоненте Router см. в разделе Маршрутизация ASP.NET Core Blazor.For more information on the Router component, see Маршрутизация ASP.NET Core Blazor.

Указание макета в качестве макета по умолчанию в маршрутизаторе достаточно полезно, так как в этом случае его можно переопределить отдельно для каждого компонента или папки.Specifying the layout as a default layout in the router is a useful practice because it can be overridden on a per-component or per-folder basis. Для настройки макета приложения по умолчанию предпочтительнее использовать маршрутизатор, поскольку это наиболее общий способ.Prefer using the router to set the app's default layout because it's the most general technique.

Указание макета в компонентеSpecify a layout in a component

Используйте директиву Razor @layout, чтобы применить макет к компоненту.Use the Razor directive @layout to apply a layout to a component. Компилятор преобразует @layout в LayoutAttribute, который применяется к классу компонента.The compiler converts @layout into a LayoutAttribute, which is applied to the component class.

Содержимое следующего компонента MasterList вставляется в MasterLayout в позиции @Body:The content of the following MasterList component is inserted into the MasterLayout at the position of @Body:

@layout MasterLayout
@page "/masterlist"

<h1>Master Episode List</h1>

Указание макета непосредственно в компоненте переопределяет макет по умолчанию , заданный в маршрутизаторе, или директиву @layout, импортированную из файла _Imports.razor.Specifying the layout directly in a component overrides a default layout set in the router or an @layout directive imported from _Imports.razor.

Централизованный выбор макетовCentralized layout selection

В каждой папке приложения может дополнительно содержаться файл шаблона с именем _Imports.razor.Every folder of an app can optionally contain a template file named _Imports.razor. Компилятор включает директивы, указанные в файле импорта, во все шаблоны Razor в одной и той же папке и рекурсивно во всех ее вложенных папках.The compiler includes the directives specified in the imports file in all of the Razor templates in the same folder and recursively in all of its subfolders. Таким образом, файл _Imports.razor, содержащий @layout MyCoolLayout, гарантирует, что все компоненты в папке используют MyCoolLayout.Therefore, an _Imports.razor file containing @layout MyCoolLayout ensures that all of the components in a folder use MyCoolLayout. Нет необходимости многократно добавлять @layout MyCoolLayout во все файлы .razor в папке и вложенных папках.There's no need to repeatedly add @layout MyCoolLayout to all of the .razor files within the folder and subfolders. Директивы @using применяются к компонентам таким же образом.@using directives are also applied to components in the same way.

Следующий файл _Imports.razor импортирует следующее:The following _Imports.razor file imports:

  • MyCoolLayout.MyCoolLayout.
  • Все компоненты Razor в одной и той же папке и во всех вложенных папках.All Razor components in the same folder and any subfolders.
  • Пространство имен BlazorApp1.Data .The BlazorApp1.Data namespace.
@layout MyCoolLayout
@using Microsoft.AspNetCore.Components
@using BlazorApp1.Data

Файл _Imports.razor аналогичен файлу _ViewImports.cshtml для представлений и страниц Razor, однако он применяется специально к файлам компонентов Razor.The _Imports.razor file is similar to the _ViewImports.cshtml file for Razor views and pages but applied specifically to Razor component files.

Указание макета в файле _Imports.razor переопределяет макет, указанный в качестве макета по умолчанию маршрутизатора.Specifying a layout in _Imports.razor overrides a layout specified as the router's default layout.

Предупреждение

Не добавляйте директиву Razor @layout к корневому файлу _Imports.razor, так как это приведет к формированию бесконечного цикла макетов в файле.Do not add a Razor @layout directive to the root _Imports.razor file, which results in an infinite loop of layouts in the app. Чтобы управлять макетом приложения по умолчанию, укажите макет в компоненте Router.To control the default app layout, specify the layout in the Router component. Дополнительные сведения см. в разделе Макет по умолчанию.For more information, see the Default layout section.

Вложенные макетыNested layouts

Приложения могут состоять из вложенных макетов.Apps can consist of nested layouts. Компонент может ссылаться на макет, который, в свою очередь, ссылается на другой макет.A component can reference a layout which in turn references another layout. Например, для создания структуры многоуровневого меню используются вложенные макеты.For example, nesting layouts are used to create a multi-level menu structure.

В следующем примере показано использование вложенных макетов.The following example shows how to use nested layouts. Файл EpisodesComponent.razor является отображаемым компонентом.The EpisodesComponent.razor file is the component to display. Компонент ссылается на MasterListLayout:The component references the MasterListLayout:

@layout MasterListLayout
@page "/masterlist/episodes"

<h1>Episodes</h1>

Файл MasterListLayout.razor предоставляет MasterListLayout.The MasterListLayout.razor file provides the MasterListLayout. Макет ссылается на другой макет, MasterLayout, где он преобразуется для просмотра.The layout references another layout, MasterLayout, where it's rendered. EpisodesComponent отображается там, где находится @Body:EpisodesComponent is rendered where @Body appears:

@layout MasterLayout
@inherits LayoutComponentBase

<nav>
    <!-- Menu structure of master list -->
    ...
</nav>

@Body

Наконец, MasterLayout в файле MasterLayout.razor содержит элементы макета верхнего уровня, такие как заголовок, главное меню и нижний колонтитул.Finally, MasterLayout in MasterLayout.razor contains the top-level layout elements, such as the header, main menu, and footer. MasterListLayout с EpisodesComponent отображается там, где находится @Body:MasterListLayout with the EpisodesComponent is rendered where @Body appears:

@inherits LayoutComponentBase

<header>...</header>
<nav>...</nav>

@Body

<footer>
    @TrademarkMessage
</footer>

@code {
    public string TrademarkMessage { get; set; } = 
        "Doctor Who is a registered trademark of the BBC. " +
        "https://www.doctorwho.tv/";
}

Совместное использование макета Razor Pages с интегрированными компонентамиShare a Razor Pages layout with integrated components

Если маршрутизируемые компоненты интегрированы в приложение Razor Pages, общий макет приложения можно использовать с компонентами.When routable components are integrated into a Razor Pages app, the app's shared layout can be used with the components. Для получения дополнительной информации см. Компоненты Razor для предварительной визуализации и интеграции ASP.NET Core.For more information, see Компоненты Razor для предварительной визуализации и интеграции ASP.NET Core.

Дополнительные ресурсыAdditional resources