Layouts Blazor do ASP.NET Core
Observação
Esta não é a versão mais recente deste artigo. Para informações sobre a versão vigente, confira a Versão do .NET 8 deste artigo.
Aviso
Esta versão do ASP.NET Core não tem mais suporte. Para obter mais informações, confira .NET e a Política de Suporte do .NET Core. Para informações sobre a versão vigente, confira a Versão do .NET 8 deste artigo.
Importante
Essas informações relacionam-se ao produto de pré-lançamento, que poderá ser substancialmente modificado antes do lançamento comercial. A Microsoft não oferece nenhuma garantia, explícita ou implícita, quanto às informações fornecidas aqui.
Para informações sobre a versão vigente, confira a Versão do .NET 8 deste artigo.
Este artigo explica como criar componentes de layout reutilizáveis para aplicativos Blazor.
Utilidade dos layouts Blazor
Alguns elementos do aplicativo, como menus, mensagens de direitos autorais e logotipos da empresa, geralmente fazem parte da apresentação geral do aplicativo. A colocação de uma cópia da marcação desses elementos em todos os componentes de um aplicativo não é eficiente. Sempre que um desses elementos é atualizado, todos os componentes que usam o elemento devem ser atualizados. Essa abordagem pode custar caro para ser mantida e pode gerar um conteúdo inconsistente se uma atualização for perdida. Os layouts resolvem esses problemas.
Um layout de Blazor é um componente de Razor que compartilha a marcação com componentes que fazem referência a ele. Os layouts podem usar associação de dados, injeção de dependência e outros recursos de componentes.
Componentes do layout
Criar um componente de layout
Para criar um componente de layout:
- Crie um componente Razor definido por um modelo Razor ou código C#. Os componentes de layout baseados em um modelo Razor usam a extensão de arquivo
.razor
, assim como os componentes Razor comuns. Como os componentes de layout são compartilhados entre os componentes de um aplicativo, eles geralmente são colocados na pastaShared
ouLayout
do aplicativo. No entanto, os layouts podem ser colocados em qualquer local acessível aos componentes que o usam. Por exemplo, um layout pode ser colocado na mesma pasta que os componentes que o usam. - Herda o componente de LayoutComponentBase. O LayoutComponentBase define uma propriedade Body (tipo RenderFragment) para o conteúdo renderizado dentro do layout.
- Use a sintaxe Razor
@Body
para especificar o local na marcação de layout em que o conteúdo é renderizado.
Observação
Para obter mais informações sobre RenderFragment, confira Componentes Razordo ASP.NET Core.
O componente DoctorWhoLayout
a seguir mostra o modelo Razor de um componente de layout. O layout herda LayoutComponentBase e define o @Body
entre a barra de navegação (<nav>...</nav>
) e o rodapé (<footer>...</footer>
).
DoctorWhoLayout.razor
:
@inherits LayoutComponentBase
<PageTitle>Doctor Who® Database</PageTitle>
<header>
<h1>Doctor Who® Database</h1>
</header>
<nav>
<a href="main-list">Main 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/ https://www.bbc.com";
}
@inherits LayoutComponentBase
<PageTitle>Doctor Who® Database</PageTitle>
<header>
<h1>Doctor Who® Database</h1>
</header>
<nav>
<a href="main-list">Main 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/ https://www.bbc.com";
}
@inherits LayoutComponentBase
<header>
<h1>Doctor Who™ Episode Database</h1>
</header>
<nav>
<a href="main-list">Main 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/";
}
@inherits LayoutComponentBase
<header>
<h1>Doctor Who™ Episode Database</h1>
</header>
<nav>
<a href="main-list">Main 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/";
}
@inherits LayoutComponentBase
<header>
<h1>Doctor Who™ Episode Database</h1>
</header>
<nav>
<a href="main-list">Main 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/";
}
@inherits LayoutComponentBase
<header>
<h1>Doctor Who™ Episode Database</h1>
</header>
<nav>
<a href="main-list">Main 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/";
}
componente MainLayout
Em um aplicativo criado com base em um modelo de projeto Blazor, o componente MainLayout
é o layout padrão do aplicativo. O layout do Blazor adota a Flexbox layout model (MDN documentation) (especificação W3C).
O recurso de isolamento CSS do Blazor aplica estilos CSS isolados ao componente MainLayout
. Por convenção, os estilos são fornecidos pela folha de estilos que acompanha o mesmo nome, MainLayout.razor.css
. A implementação da estrutura ASP.NET Core da folha de estilos está disponível para inspeção na fonte de referência do ASP.NET Core (repositório GitHub dotnet/aspnetcore
):
Observação
Os links de documentação para a fonte de referência do .NET geralmente carregam o branch padrão do repositório, que representa o desenvolvimento atual da próxima versão do .NET. Para selecionar uma marca para uma versão específica, use a lista suspensa para Alternar branches ou marcas. Para saber mais, confira Como selecionar uma marca de versão do código-fonte do ASP.NET Core (dotnet/AspNetCore.Docs #26205).
O recurso de isolamento CSS do Blazor aplica estilos CSS isolados ao componente MainLayout
. Por convenção, os estilos são fornecidos pela folha de estilos que acompanha o mesmo nome, MainLayout.razor.css
. A implementação da estrutura ASP.NET Core da folha de estilos está disponível para inspeção na fonte de referência do ASP.NET Core (repositório GitHub dotnet/aspnetcore
):
Observação
Os links de documentação para a fonte de referência do .NET geralmente carregam o branch padrão do repositório, que representa o desenvolvimento atual da próxima versão do .NET. Para selecionar uma marca para uma versão específica, use a lista suspensa para Alternar branches ou marcas. Para saber mais, confira Como selecionar uma marca de versão do código-fonte do ASP.NET Core (dotnet/AspNetCore.Docs #26205).
Aplicar um layout
Disponibilizar o namespace de layout
Locais de arquivo de layout e namespaces alterados ao longo do tempo para a estrutura Blazor. Dependendo da versão de Blazor e do tipo do aplicativo Blazor que você está criando, talvez seja necessário indicar o namespace do layout ao usá-lo. Ao referenciar uma implementação de layout e o layout não for encontrado sem indicar o namespace do layout, siga qualquer uma das seguintes abordagens:
Adicione uma diretiva
@using
ao arquivo_Imports.razor
para o local dos layouts. No exemplo a seguir, uma pasta de layouts com o nomeLayout
está dentro de uma pastaComponents
e o namespace do aplicativo éBlazorSample
:@using BlazorSample.Components.Layout
Adicione uma diretiva
@using
no topo da definição do componente onde o layout é usado:@using BlazorSample.Components.Layout @layout DoctorWhoLayout
Qualifique totalmente o namespace do layout em que ele é usado:
@layout BlazorSample.Components.Layout.DoctorWhoLayout
Aplicar um layout a um componente
Use a diretiva @layout
Razor para aplicar um layout a um componente Razor roteável que tenha uma diretiva @page
. O compilador converte @layout
em um LayoutAttribute e aplica o atributo à classe de componente.
O conteúdo do componente Episodes
a seguir é inserido no DoctorWhoLayout
na posição de @Body
.
Episodes.razor
:
@page "/episodes"
@layout DoctorWhoLayout
<h2>Doctor Who® Episodes</h2>
<ul>
<li>
<a href="https://www.bbc.co.uk/programmes/p00vfknq">
<em>The Ribos Operation</em>
</a>
</li>
<li>
<a href="https://www.bbc.co.uk/programmes/p00vfdsb">
<em>The Sunmakers</em>
</a>
</li>
<li>
<a href="https://www.bbc.co.uk/programmes/p00vhc26">
<em>Nightmare of Eden</em>
</a>
</li>
</ul>
@page "/episodes"
@layout DoctorWhoLayout
<h2>Doctor Who® Episodes</h2>
<ul>
<li>
<a href="https://www.bbc.co.uk/programmes/p00vfknq">
<em>The Ribos Operation</em>
</a>
</li>
<li>
<a href="https://www.bbc.co.uk/programmes/p00vfdsb">
<em>The Sunmakers</em>
</a>
</li>
<li>
<a href="https://www.bbc.co.uk/programmes/p00vhc26">
<em>Nightmare of Eden</em>
</a>
</li>
</ul>
@page "/episodes"
@layout DoctorWhoLayout
<h2>Episodes</h2>
<ul>
<li>
<a href="https://www.bbc.co.uk/programmes/p00vfknq">
<em>The Ribos Operation</em>
</a>
</li>
<li>
<a href="https://www.bbc.co.uk/programmes/p00vfdsb">
<em>The Sun Makers</em>
</a>
</li>
<li>
<a href="https://www.bbc.co.uk/programmes/p00vhc26">
<em>Nightmare of Eden</em>
</a>
</li>
</ul>
@page "/episodes"
@layout DoctorWhoLayout
<h2>Episodes</h2>
<ul>
<li>
<a href="https://www.bbc.co.uk/programmes/p00vfknq">
<em>The Ribos Operation</em>
</a>
</li>
<li>
<a href="https://www.bbc.co.uk/programmes/p00vfdsb">
<em>The Sun Makers</em>
</a>
</li>
<li>
<a href="https://www.bbc.co.uk/programmes/p00vhc26">
<em>Nightmare of Eden</em>
</a>
</li>
</ul>
@page "/episodes"
@layout DoctorWhoLayout
<h2>Episodes</h2>
<ul>
<li>
<a href="https://www.bbc.co.uk/programmes/p00vfknq">
<em>The Ribos Operation</em>
</a>
</li>
<li>
<a href="https://www.bbc.co.uk/programmes/p00vfdsb">
<em>The Sun Makers</em>
</a>
</li>
<li>
<a href="https://www.bbc.co.uk/programmes/p00vhc26">
<em>Nightmare of Eden</em>
</a>
</li>
</ul>
A marcação HTML renderizada a seguir é produzida pelo componente anterior DoctorWhoLayout
e Episodes
. A marcação desnecessária não aparece para se concentrar no conteúdo fornecido pelos dois componentes envolvidos:
- O título H1 do "banco de dados" (
<h1>...</h1>
) no cabeçalho (<header>...</header>
), a barra de navegação (<nav>...</nav>
) e as informações de marca registrada no rodapé (<footer>...</footer>
) são provenientes do componenteDoctorWhoLayout
. - O título H2 "episódios" (
<h2>...</h2>
) e a lista de episódios (<ul>...</ul>
) vêm do componenteEpisodes
.
<header>
<h1 ...>...</h1>
</header>
<nav>
...
</nav>
<h2>...</h2>
<ul>
<li>...</li>
<li>...</li>
<li>...</li>
</ul>
<footer>
...
</footer>
A especificação do layout diretamente em um componente substitui um layout padrão:
- Definido por uma diretiva
@layout
importada de um arquivo_Imports.razor
, conforme descrito na seção Aplicar um layout a uma pasta de componentes a seguir. - Defina como o layout padrão do aplicativo, conforme descrito na seção Aplicar um layout padrão a um aplicativo mais adiante neste artigo.
Aplicar um layout a uma pasta de componentes
Cada pasta de um aplicativo pode, opcionalmente, conter um arquivo de modelo nomeado _Imports.razor
. O compilador inclui as diretivas especificadas no arquivo de importações em todos os modelos Razor na mesma pasta e recursivamente em todas as suas subpastas. Portanto, um arquivo _Imports.razor
que contém @layout DoctorWhoLayout
garante que todos os componentes em uma pasta usem o componente DoctorWhoLayout
. Não é necessário adicionar @layout DoctorWhoLayout
repetidamente a todos os componentes Razor (.razor
) dentro da pasta e das subpastas.
_Imports.razor
:
@layout DoctorWhoLayout
...
O arquivo _Imports.razor
é semelhante ao arquivo _ViewImports.cshtml para exibições Razor e páginas, mas aplicado especificamente aos arquivos de componente Razor.
A especificação de um layout em _Imports.razor
substitui um layout especificado como layout de aplicativo padrão do roteador, que é descrito na seção a seguir.
Aviso
Não adicione uma diretiva Razor@layout
ao arquivo _Imports.razor
raiz, o que resulta em um loop infinito de layouts. Para controlar o layout do aplicativo padrão, especifique o layout no componente Router. Para obter mais informações, consulte a seção Aplicar um layout padrão a um aplicativo a seguir.
Observação
A diretiva @layout
Razor aplica apenas um layout a componentes roteáveis Razor com uma diretiva @page
.
Aplicar um layout padrão a um aplicativo
Especifique o layout do aplicativo padrão no componente RouteView do componente Router. Use o parâmetro DefaultLayout para definir o tipo de layout:
<RouteView RouteData="routeData" DefaultLayout="typeof({LAYOUT})" />
No exemplo anterior, o espaço reservado {LAYOUT}
é o layout (por exemplo, DoctorWhoLayout
se o nome do arquivo de layout for DoctorWhoLayout.razor
). Talvez seja necessário identificar o namespace do layout, dependendo da versão do .NET e do tipo do aplicativo Blazor. Para obter mais informações, consulte a seção Disponibilizar o namespace de layout.
A especificação do layout como um layout padrão no Router do RouteView do componente é uma prática útil porque você pode substituir o layout por componente ou por pasta, conforme descrito nas seções anteriores deste artigo. É recomendável usar o componente Router para definir o layout padrão do aplicativo, pois ele é a abordagem mais geral e flexível para usar layouts.
Aplicar um layout ao conteúdo arbitrário (componente LayoutView
)
Para definir um layout para conteúdo de modelo arbitrário Razor, especifique o layout com um componente LayoutView. Você pode usar um LayoutView em qualquer componente Razor. O exemplo a seguir define um componente de layout nomeado ErrorLayout
para o modelo NotFound do componente MainLayout
(<NotFound>...</NotFound>
).
<Router ...>
<Found ...>
...
</Found>
<NotFound>
<LayoutView Layout="typeof(ErrorLayout)">
<h1>Page not found</h1>
<p>Sorry, there's nothing at this address.</p>
</LayoutView>
</NotFound>
</Router>
Talvez seja necessário identity o namespace do layout, dependendo da versão do .NET e do tipo do aplicativo Blazor. Para obter mais informações, consulte a seção Disponibilizar o namespace de layout.
Importante
Os Blazor Web App não usam o parâmetro NotFound (marcação <NotFound>...</NotFound>
), mas o parâmetro tem suporte para compatibilidade com versões anteriores, a fim de evitar uma alteração interruptiva na estrutura. O pipeline de middleware ASP.NET Core do lado do servidor processa solicitações no servidor. Use as técnicas do servidor para tratar as solicitações incorretas. Para obter mais informações, consulte ASP.NET Core Blazor modos de renderização.
Observação
Com a versão do ASP.NET Core 5.0.1 e para qualquer lançamento adicional do 5.x, o componente Router
inclui o parâmetro PreferExactMatches
definido como @true
. Para obter mais informações, consulte Migrar do ASP.NET Core 3.1 para o 5.0.
Layouts aninhados
Um componente pode fazer referência a um layout que, por sua vez, faz referência a outro layout. Por exemplo, layouts aninhados são usados para criar estruturas de menu de vários níveis.
O exemplo a seguir mostra como usar os layouts aninhados. O componente Episodes
mostrado na seção Aplicar um layout a um componente é o componente a ser exibido. O componente faz referência ao componente DoctorWhoLayout
.
O componente DoctorWhoLayout
a seguir é uma versão modificada do exemplo mostrado anteriormente neste artigo. Os elementos de cabeçalho e rodapé são removidos e o layout faz referência a outro layout, ProductionsLayout
. O componente Episodes
é renderizado onde @Body
aparece no DoctorWhoLayout
.
DoctorWhoLayout.razor
:
@inherits LayoutComponentBase
@layout ProductionsLayout
<PageTitle>Doctor Who® Database</PageTitle>
<h1>Doctor Who® Database</h1>
<nav>
<a href="main-episode-list">Main Episode List</a>
<a href="episode-search">Search</a>
<a href="new-episode">Add Episode</a>
</nav>
@Body
<div>
@TrademarkMessage
</div>
@code {
public string TrademarkMessage { get; set; } =
"Doctor Who is a registered trademark of the BBC. " +
"https://www.doctorwho.tv/ https://www.bbc.com";
}
@inherits LayoutComponentBase
@layout ProductionsLayout
<PageTitle>Doctor Who® Database</PageTitle>
<h1>Doctor Who® Database</h1>
<nav>
<a href="main-episode-list">Main Episode List</a>
<a href="episode-search">Search</a>
<a href="new-episode">Add Episode</a>
</nav>
@Body
<div>
@TrademarkMessage
</div>
@code {
public string TrademarkMessage { get; set; } =
"Doctor Who is a registered trademark of the BBC. " +
"https://www.doctorwho.tv/ https://www.bbc.com";
}
@inherits LayoutComponentBase
@layout ProductionsLayout
<h1>Doctor Who™ Episode Database</h1>
<nav>
<a href="main-episode-list">Main Episode List</a>
<a href="episode-search">Search</a>
<a href="new-episode">Add Episode</a>
</nav>
@Body
<div>
@TrademarkMessage
</div>
@code {
public string TrademarkMessage { get; set; } =
"Doctor Who is a registered trademark of the BBC. " +
"https://www.doctorwho.tv/";
}
@inherits LayoutComponentBase
@layout ProductionsLayout
<h1>Doctor Who™ Episode Database</h1>
<nav>
<a href="main-episode-list">Main Episode List</a>
<a href="episode-search">Search</a>
<a href="new-episode">Add Episode</a>
</nav>
@Body
<div>
@TrademarkMessage
</div>
@code {
public string TrademarkMessage { get; set; } =
"Doctor Who is a registered trademark of the BBC. " +
"https://www.doctorwho.tv/";
}
@inherits LayoutComponentBase
@layout ProductionsLayout
<h1>Doctor Who™ Episode Database</h1>
<nav>
<a href="main-episode-list">Main Episode List</a>
<a href="episode-search">Search</a>
<a href="new-episode">Add Episode</a>
</nav>
@Body
<div>
@TrademarkMessage
</div>
@code {
public string TrademarkMessage { get; set; } =
"Doctor Who is a registered trademark of the BBC. " +
"https://www.doctorwho.tv/";
}
@inherits LayoutComponentBase
@layout ProductionsLayout
<h1>Doctor Who™ Episode Database</h1>
<nav>
<a href="main-episode-list">Main Episode List</a>
<a href="episode-search">Search</a>
<a href="new-episode">Add Episode</a>
</nav>
@Body
<div>
@TrademarkMessage
</div>
@code {
public string TrademarkMessage { get; set; } =
"Doctor Who is a registered trademark of the BBC. " +
"https://www.doctorwho.tv/";
}
O componente ProductionsLayout
contém os elementos de layout de nível superior, em que os elementos de cabeçalho (<header>...</header>
) e rodapé (<footer>...</footer>
) agora residem. O DoctorWhoLayout
com o componente Episodes
é renderizado onde @Body
aparece.
ProductionsLayout.razor
:
@inherits LayoutComponentBase
<header>
<h1>Productions</h1>
</header>
<nav>
<a href="main-production-list">Main Production List</a>
<a href="production-search">Search</a>
<a href="new-production">Add Production</a>
</nav>
@Body
<footer>
Footer of Productions Layout
</footer>
@inherits LayoutComponentBase
<header>
<h1>Productions</h1>
</header>
<nav>
<a href="main-production-list">Main Production List</a>
<a href="production-search">Search</a>
<a href="new-production">Add Production</a>
</nav>
@Body
<footer>
Footer of Productions Layout
</footer>
@inherits LayoutComponentBase
<header>
<h1>Productions</h1>
</header>
<nav>
<a href="main-production-list">Main Production List</a>
<a href="production-search">Search</a>
<a href="new-production">Add Production</a>
</nav>
@Body
<footer>
Footer of Productions Layout
</footer>
@inherits LayoutComponentBase
<header>
<h1>Productions</h1>
</header>
<nav>
<a href="main-production-list">Main Production List</a>
<a href="production-search">Search</a>
<a href="new-production">Add Production</a>
</nav>
@Body
<footer>
Footer of Productions Layout
</footer>
@inherits LayoutComponentBase
<header>
<h1>Productions</h1>
</header>
<nav>
<a href="main-production-list">Main Production List</a>
<a href="production-search">Search</a>
<a href="new-production">Add Production</a>
</nav>
@Body
<footer>
Footer of Productions Layout
</footer>
@inherits LayoutComponentBase
<header>
<h1>Productions</h1>
</header>
<nav>
<a href="main-production-list">Main Production List</a>
<a href="production-search">Search</a>
<a href="new-production">Add Production</a>
</nav>
@Body
<footer>
Footer of Productions Layout
</footer>
A marcação HTML renderizada a seguir é produzida pelo layout aninhado anterior. A marcação desnecessária não aparece para se concentrar no conteúdo aninhado fornecido pelos três componentes envolvidos:
- Os elementos de cabeçalho (
<header>...</header>
), barra de navegação de produção (<nav>...</nav>
) e rodapé (<footer>...</footer>
) e seu conteúdo são derivados do componenteProductionsLayout
. - O título H1 do "banco de dados" (
<h1>...</h1>
), a barra de navegação de episódios (<nav>...</nav>
) e as informações de marca registrada (<div>...</div>
) vêm do componenteDoctorWhoLayout
. - O título H2 "episódios" (
<h2>...</h2>
) e a lista de episódios (<ul>...</ul>
) vêm do componenteEpisodes
.
<header>
...
</header>
<nav>
<a href="main-production-list">Main Production List</a>
<a href="production-search">Search</a>
<a href="new-production">Add Production</a>
</nav>
<h1>...</h1>
<nav>
<a href="main-episode-list">Main Episode List</a>
<a href="episode-search">Search</a>
<a href="new-episode">Add Episode</a>
</nav>
<h2>...</h2>
<ul>
<li>...</li>
<li>...</li>
<li>...</li>
</ul>
<div>
...
</div>
<footer>
...
</footer>
Compartilhar um layout do Razor Pages com componentes integrados
Quando componentes roteáveis são integrados a um aplicativo Razor Pages, o layout compartilhado do aplicativo pode ser usado com os componentes. Para obter mais informações, consulte Integrar componentes Razor do ASP.NET Core em aplicativos do ASP.NET Core.
Quando componentes roteáveis são integrados a um aplicativo Razor Pages, o layout compartilhado do aplicativo pode ser usado com os componentes. Para obter mais informações, confira Renderizar previamente e integrar os componentes Razor do ASP.NET Core.
Seções
Para controlar o conteúdo em um layout a partir de um componente-filho Razor, consulte as seções ASP.NET Core Blazor.