Diseños de ASP.NET Core Blazor
Algunos elementos de la aplicación, como los menús, los mensajes de copyright y los logotipos de la empresa, suelen formar parte del diseño general de la aplicación. Colocar una copia del marcado de estos elementos en todos los componentes de una aplicación no es eficaz. Cada vez que uno de estos elementos se actualice, deberán actualizarse todos los componentes que dicho elemento use. Este método es costoso de mantener y puede dar lugar a contenido incoherente si una actualización no se lleva a cabo. Los diseños resuelven este tipo de problemas.
Un diseño de Blazor es un componente Razor que comparte el marcado con los componentes que hacen referencia a él. Los diseños pueden usar características de los componentes, como el enlace de datos y la inserción de dependencias, entre otras.
Componentes de diseño
Creación de un componente de diseño
Para crear un componente de diseño:
- Cree un componente Razor definido por una plantilla Razor o código de C#. Los componentes de diseño basados en una plantilla Razor usan la extensión de archivo
.razor, igual que cualquier otro componente Razor normal. Dado que los componentes de diseño se comparten entre los componentes de una aplicación, se suelen colocar en la carpetaSharedde la aplicación, pero pueden colocarse en cualquier ubicación a la que tengan acceso los componentes que lo usan. Por ejemplo, un diseño se puede colocar en la misma carpeta que los componentes que lo usan. - Herede el componente de LayoutComponentBase. LayoutComponentBase define una propiedad Body (de tipo RenderFragment) para el contenido representado dentro del diseño.
- Use la sintaxis
@Bodyde Razor para especificar la ubicación en el marcado de diseño donde se representa el contenido.
El siguiente componente DoctorWhoLayout muestra la plantilla Razor de un componente de diseño. El diseño hereda LayoutComponentBase y establece @Body entre la barra de navegación (<nav>...</nav>) y el pie de página (<footer>...</footer>).
Shared/DoctorWhoLayout.razor:
@inherits LayoutComponentBase
<header>
<h1>Doctor Who™ 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/";
}
Componente de MainLayout
En una aplicación creada a partir de una plantilla de proyecto de Blazor, el componente MainLayout es el diseño predeterminado de la aplicación.
Shared/MainLayout.razor:
@inherits LayoutComponentBase
<div class="page">
<div class="sidebar">
<NavMenu />
</div>
<div class="main">
<div class="top-row px-4">
<a href="http://blazor.net" target="_blank" class="ml-md-auto">About</a>
</div>
<div class="content px-4">
@Body
</div>
</div>
</div>
La característica de aislamiento CSS de Blazor aplica estilos CSS aislados al componente MainLayout. Por convención, los estilos los proporciona la hoja de estilos del mismo nombre que los acompaña, Shared/MainLayout.razor.css. La implementación del marco ASP.NET Core de la hoja de estilos está disponible para su inspección en Origen de referencia de ASP.NET Core (repositorio de GitHub dotnet/aspnetcore).
Nota
Los enlaces de la documentación del origen de referencia de ASP.NET Core cargan la rama main del repositorio, que representa el desarrollo actual de la unidad de producto para la próxima versión de ASP.NET Core. Para seleccionar la rama de una versión diferente, use la lista desplegable Switch branches or tags (Cambiar ramas o etiquetas) para seleccionar la rama. Por ejemplo, seleccione la rama release/5.0 para la versión 5.0 de ASP.NET Core.
Aplicación de un diseño
Aplicación de diseño a un componente
Use la directiva @layout de Razor para aplicar un diseño a un componente de Razor enrutable que tenga una directiva @page. El compilador convierte @layout en LayoutAttribute y aplica el atributo a la clase de componente.
El contenido del siguiente componente Episodes se inserta en DoctorWhoLayout en la posición @Body.
Pages/Episodes.razor:
@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>
El siguiente marcado HTML representado lo genera el componente DoctorWhoLayout anterior y el componente Episodes. El marcado extraño no se muestra para centrarnos en el contenido proporcionado por los dos componentes implicados:
- El título Doctor Who™ Episode Database (
<h1>...</h1>) del encabezado (<header>...</header>), la barra de navegación (<nav>...</nav>) y el elemento informativo de marca comercial (<div>...</div>) del pie de página (<footer>...</footer>) proceden del componenteDoctorWhoLayout. - El título Episodes (
<h2>...</h2>) y la lista de episodios (<ul>...</ul>) proceden del componenteEpisodes.
<body>
<div id="app">
<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>
<h2>Episodes</h2>
<ul>
<li>...</li>
<li>...</li>
<li>...</li>
</ul>
<footer>
Doctor Who is a registered trademark of the BBC.
https://www.doctorwho.tv/
</footer>
</div>
</body>
Al especificar el diseño directamente en un componente, se reemplaza un diseño predeterminado que:
- Se ha establecido mediante una directiva
@layoutimportada de un componente_Imports(_Imports.razor), como se describe en la sección Aplicación de un diseño a una carpeta de componentes. - Se ha establecido como el diseño predeterminado de la aplicación, como se describe en la sección Aplicación de un diseño predeterminado a una aplicación más adelante en este artículo.
Aplicación de un diseño a una carpeta de componentes
Cada una de las carpetas de una aplicación puede contener opcionalmente un archivo de plantilla denominado _Imports.razor. El compilador incluye las directivas especificadas en el archivo de importaciones de todas las plantillas de Razor de la misma carpeta y, de forma recurrente, de todas sus subcarpetas. Por lo tanto, un archivo _Imports.razor que contiene @layout DoctorWhoLayout garantiza que todos los componentes de una carpeta usen el componente DoctorWhoLayout. No es necesario agregar continuamente @layout DoctorWhoLayout a todos los componentes Razor (.razor) dentro de la carpeta y las subcarpetas.
_Imports.razor:
@layout DoctorWhoLayout
...
El archivo _Imports.razor es similar al archivo _ViewImports.cshtml de las vistas y las páginas de Razor, aunque se aplica específicamente a los archivos de componentes de Razor.
Cuando se especifica un diseño en _Imports.razor, este reemplaza el diseño especificado como diseño de la aplicación predeterminado del enrutador. Esto se describe en la siguiente sección.
Advertencia
No agregue una directiva @layout de Razor al archivo raíz _Imports.razor, que da como resultado un bucle infinito de diseños. Para controlar el diseño predeterminado de la aplicación, especifique el diseño en el componente Router. Para obtener más información, vea la sección Aplicación de un diseño predeterminado a una aplicación.
Nota
La directiva @layout de Razor únicamente aplica un diseño a los componentes Razor enrutables con una directiva @page.
Aplicación de un diseño predeterminado a una aplicación
Especifique el diseño predeterminado de la aplicación en el componente Router del componente App. En el siguiente ejemplo de una aplicación basada en una plantilla de proyecto de Blazor, el diseño predeterminado se establece en el componente MainLayout.
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>
Para obtener más información sobre el componente Router, consulte el artículo Enrutamiento de Blazor de ASP.NET Core.
Especificar el diseño como un diseño predeterminado en el componente Router es útil en el sentido de que permite reemplazar el diseño según el componente o la carpeta, como se describe en las secciones anteriores de este artículo. Se recomienda usar el componente Router para establecer el diseño predeterminado de la aplicación, ya que es el método más general y flexible de uso de diseños.
Aplicación de un diseño a contenido arbitrario (componente LayoutView)
Para establecer el diseño del contenido arbitrario de una plantilla Razor, especifique el diseño con un componente LayoutView. LayoutView se puede usar en cualquier componente Razor. En el siguiente ejemplo se establece un componente de diseño denominado ErrorLayout para la plantilla NotFound del componente MainLayout (<NotFound>...</NotFound>).
App.razor:
<Router AppAssembly="@typeof(Program).Assembly">
<Found Context="routeData">
<RouteView RouteData="@routeData" DefaultLayout="@typeof(MainLayout)" />
</Found>
<NotFound>
<LayoutView Layout="@typeof(ErrorLayout)">
<h1>Page not found</h1>
<p>Sorry, there's nothing at this address.</p>
</LayoutView>
</NotFound>
</Router>
Diseños anidados
Un componente puede hacer referencia a un diseño que, a su vez, hace referencia a otro diseño. Por ejemplo, los diseños anidados se usan para crear una estructura de menú de varios niveles.
En el ejemplo siguiente se muestra cómo usar los diseños anidados. El componente Episodes de la sección Aplicación de un diseño a un componente es el componente que se va a mostrar. El componente hace referencia al componente DoctorWhoLayout.
El siguiente componente DoctorWhoLayout es una versión modificada del ejemplo que vimos antes en este artículo. Se le han quitado los elementos de encabezado y pie de página, y el diseño hace referencia a otro diseño, ProductionsLayout. El componente Episodes se representa cuando @Body aparece en DoctorWhoLayout.
Shared/DoctorWhoLayout.razor:
@inherits LayoutComponentBase
@layout ProductionsLayout
<h1>Doctor Who™ Episode Database</h1>
<nav>
<a href="episode-masterlist">Master 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/";
}
El componente ProductionsLayout contiene los elementos de diseño de nivel superior, donde ahora están los elementos de encabezado (<header>...</header>) y pie de página (<footer>...</footer>). El componente DoctorWhoLayout con el componente Episodes se representa donde aparezca @Body.
Shared/ProductionsLayout.razor:
@inherits LayoutComponentBase
<header>
<h1>Productions</h1>
</header>
<nav>
<a href="master-production-list">Master Production List</a>
<a href="production-search">Search</a>
<a href="new-production">Add Production</a>
</nav>
@Body
<footer>
Footer of Productions Layout
</footer>
El siguiente marcado HTML representado lo genera el diseño anidado anterior. El marcado extraño no se muestra para centrarnos en el contenido anidado proporcionado por los tres componentes implicados:
- Los elementos de encabezado (
<header>...</header>), barra de navegación de producción (<nav>...</nav>) y pie de página (<footer>...</footer>), y su contenido proceden del componenteProductionsLayout. - El título Doctor Who™ Episode Database (
<h1>...</h1>), la barra de navegación de episodios (<nav>...</nav>) y el elemento informativo de marca comercial (<div>...</div>) proceden del componenteDoctorWhoLayout. - El título Episodes (
<h2>...</h2>) y la lista de episodios (<ul>...</ul>) proceden del componenteEpisodes.
<body>
<div id="app">
<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>
<h1>Doctor Who™ Episode Database</h1>
<nav>
<a href="episode-main-list">Main Episode List</a>
<a href="episode-search">Search</a>
<a href="new-episode">Add Episode</a>
</nav>
<h2>Episodes</h2>
<ul>
<li>...</li>
<li>...</li>
<li>...</li>
</ul>
<div>
Doctor Who is a registered trademark of the BBC.
https://www.doctorwho.tv/
</div>
<footer>
Footer of Productions Layout
</footer>
</div>
</body>
Uso compartido de un diseño de Razor Pages con componentes integrados
Si los componentes enrutables se integran en una aplicación de Razor Pages, el diseño compartido de la aplicación se puede usar con los componentes. Para obtener más información, vea Integración y representación previa de componentes Razor de ASP.NET Core.
Recursos adicionales
Algunos elementos de la aplicación, como los menús, los mensajes de copyright y los logotipos de la empresa, suelen formar parte del diseño general de la aplicación. Colocar una copia del marcado de estos elementos en todos los componentes de una aplicación no es eficaz. Cada vez que uno de estos elementos se actualice, deberán actualizarse todos los componentes que dicho elemento use. Este método es costoso de mantener y puede dar lugar a contenido incoherente si una actualización no se lleva a cabo. Los diseños resuelven este tipo de problemas.
Un diseño de Blazor es un componente Razor que comparte el marcado con los componentes que hacen referencia a él. Los diseños pueden usar características de los componentes, como el enlace de datos y la inserción de dependencias, entre otras.
Componentes de diseño
Creación de un componente de diseño
Para crear un componente de diseño:
- Cree un componente Razor definido por una plantilla Razor o código de C#. Los componentes de diseño basados en una plantilla Razor usan la extensión de archivo
.razor, igual que cualquier otro componente Razor normal. Dado que los componentes de diseño se comparten entre los componentes de una aplicación, se suelen colocar en la carpetaSharedde la aplicación, pero pueden colocarse en cualquier ubicación a la que tengan acceso los componentes que lo usan. Por ejemplo, un diseño se puede colocar en la misma carpeta que los componentes que lo usan. - Herede el componente de LayoutComponentBase. LayoutComponentBase define una propiedad Body (de tipo RenderFragment) para el contenido representado dentro del diseño.
- Use la sintaxis
@Bodyde Razor para especificar la ubicación en el marcado de diseño donde se representa el contenido.
El siguiente componente DoctorWhoLayout muestra la plantilla Razor de un componente de diseño. El diseño hereda LayoutComponentBase y establece @Body entre la barra de navegación (<nav>...</nav>) y el pie de página (<footer>...</footer>).
Shared/DoctorWhoLayout.razor:
@inherits LayoutComponentBase
<header>
<h1>Doctor Who™ 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/";
}
Componente de MainLayout
En una aplicación creada a partir de una plantilla de proyecto de Blazor, el componente MainLayout es el diseño predeterminado de la aplicación.
Shared/MainLayout.razor:
@inherits LayoutComponentBase
<div class="page">
<div class="sidebar">
<NavMenu />
</div>
<div class="main">
<div class="top-row px-4">
<a href="http://blazor.net" target="_blank" class="ml-md-auto">About</a>
</div>
<div class="content px-4">
@Body
</div>
</div>
</div>
La característica de aislamiento CSS de Blazor aplica estilos CSS aislados al componente MainLayout. Por convención, los estilos los proporciona la hoja de estilos del mismo nombre que los acompaña, Shared/MainLayout.razor.css. La implementación del marco ASP.NET Core de la hoja de estilos está disponible para su inspección en Origen de referencia de ASP.NET Core (repositorio de GitHub dotnet/aspnetcore).
Nota
Los enlaces de la documentación del origen de referencia de ASP.NET Core cargan la rama main del repositorio, que representa el desarrollo actual de la unidad de producto para la próxima versión de ASP.NET Core. Para seleccionar la rama de una versión diferente, use la lista desplegable Switch branches or tags (Cambiar ramas o etiquetas) para seleccionar la rama. Por ejemplo, seleccione la rama release/5.0 para la versión 5.0 de ASP.NET Core.
Aplicación de un diseño
Aplicación de diseño a un componente
Use la directiva @layout de Razor para aplicar un diseño a un componente de Razor enrutable que tenga una directiva @page. El compilador convierte @layout en LayoutAttribute y aplica el atributo a la clase de componente.
El contenido del siguiente componente Episodes se inserta en DoctorWhoLayout en la posición @Body.
Pages/Episodes.razor:
@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>
El siguiente marcado HTML representado lo genera el componente DoctorWhoLayout anterior y el componente Episodes. El marcado extraño no se muestra para centrarnos en el contenido proporcionado por los dos componentes implicados:
- El título Doctor Who™ Episode Database (
<h1>...</h1>) del encabezado (<header>...</header>), la barra de navegación (<nav>...</nav>) y el elemento informativo de marca comercial (<div>...</div>) del pie de página (<footer>...</footer>) proceden del componenteDoctorWhoLayout. - El título Episodes (
<h2>...</h2>) y la lista de episodios (<ul>...</ul>) proceden del componenteEpisodes.
<body>
<div id="app">
<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>
<h2>Episodes</h2>
<ul>
<li>...</li>
<li>...</li>
<li>...</li>
</ul>
<footer>
Doctor Who is a registered trademark of the BBC.
https://www.doctorwho.tv/
</footer>
</div>
</body>
Al especificar el diseño directamente en un componente, se reemplaza un diseño predeterminado que:
- Se ha establecido mediante una directiva
@layoutimportada de un componente_Imports(_Imports.razor), como se describe en la sección Aplicación de un diseño a una carpeta de componentes. - Se ha establecido como el diseño predeterminado de la aplicación, como se describe en la sección Aplicación de un diseño predeterminado a una aplicación más adelante en este artículo.
Aplicación de un diseño a una carpeta de componentes
Cada una de las carpetas de una aplicación puede contener opcionalmente un archivo de plantilla denominado _Imports.razor. El compilador incluye las directivas especificadas en el archivo de importaciones de todas las plantillas de Razor de la misma carpeta y, de forma recurrente, de todas sus subcarpetas. Por lo tanto, un archivo _Imports.razor que contiene @layout DoctorWhoLayout garantiza que todos los componentes de una carpeta usen el componente DoctorWhoLayout. No es necesario agregar continuamente @layout DoctorWhoLayout a todos los componentes Razor (.razor) dentro de la carpeta y las subcarpetas.
_Imports.razor:
@layout DoctorWhoLayout
...
El archivo _Imports.razor es similar al archivo _ViewImports.cshtml de las vistas y las páginas de Razor, aunque se aplica específicamente a los archivos de componentes de Razor.
Cuando se especifica un diseño en _Imports.razor, este reemplaza el diseño especificado como diseño de la aplicación predeterminado del enrutador. Esto se describe en la siguiente sección.
Advertencia
No agregue una directiva @layout de Razor al archivo raíz _Imports.razor, que da como resultado un bucle infinito de diseños. Para controlar el diseño predeterminado de la aplicación, especifique el diseño en el componente Router. Para obtener más información, vea la sección Aplicación de un diseño predeterminado a una aplicación.
Nota
La directiva @layout de Razor únicamente aplica un diseño a los componentes Razor enrutables con una directiva @page.
Aplicación de un diseño predeterminado a una aplicación
Especifique el diseño predeterminado de la aplicación en el componente Router del componente App. En el siguiente ejemplo de una aplicación basada en una plantilla de proyecto de Blazor, el diseño predeterminado se establece en el componente MainLayout.
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>
Nota
Con la publicación de ASP.NET Core 5.0.1 y para las versiones 5.x adicionales, el componente Router incluye el parámetro PreferExactMatches establecido en @true. Para más información, consulte Migración de ASP.NET Core 3.1 a 5.0.
Para obtener más información sobre el componente Router, consulte el artículo Enrutamiento de Blazor de ASP.NET Core.
Especificar el diseño como un diseño predeterminado en el componente Router es útil en el sentido de que permite reemplazar el diseño según el componente o la carpeta, como se describe en las secciones anteriores de este artículo. Se recomienda usar el componente Router para establecer el diseño predeterminado de la aplicación, ya que es el método más general y flexible de uso de diseños.
Aplicación de un diseño a contenido arbitrario (componente LayoutView)
Para establecer el diseño del contenido arbitrario de una plantilla Razor, especifique el diseño con un componente LayoutView. LayoutView se puede usar en cualquier componente Razor. En el siguiente ejemplo se establece un componente de diseño denominado ErrorLayout para la plantilla NotFound del componente MainLayout (<NotFound>...</NotFound>).
App.razor:
<Router AppAssembly="@typeof(Program).Assembly">
<Found Context="routeData">
<RouteView RouteData="@routeData" DefaultLayout="@typeof(MainLayout)" />
</Found>
<NotFound>
<LayoutView Layout="@typeof(ErrorLayout)">
<h1>Page not found</h1>
<p>Sorry, there's nothing at this address.</p>
</LayoutView>
</NotFound>
</Router>
Nota
Con la publicación de ASP.NET Core 5.0.1 y para las versiones 5.x adicionales, el componente Router incluye el parámetro PreferExactMatches establecido en @true. Para más información, consulte Migración de ASP.NET Core 3.1 a 5.0.
Diseños anidados
Un componente puede hacer referencia a un diseño que, a su vez, hace referencia a otro diseño. Por ejemplo, los diseños anidados se usan para crear una estructura de menú de varios niveles.
En el ejemplo siguiente se muestra cómo usar los diseños anidados. El componente Episodes de la sección Aplicación de un diseño a un componente es el componente que se va a mostrar. El componente hace referencia al componente DoctorWhoLayout.
El siguiente componente DoctorWhoLayout es una versión modificada del ejemplo que vimos antes en este artículo. Se le han quitado los elementos de encabezado y pie de página, y el diseño hace referencia a otro diseño, ProductionsLayout. El componente Episodes se representa cuando @Body aparece en DoctorWhoLayout.
Shared/DoctorWhoLayout.razor:
@inherits LayoutComponentBase
@layout ProductionsLayout
<h1>Doctor Who™ Episode Database</h1>
<nav>
<a href="episode-masterlist">Master 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/";
}
El componente ProductionsLayout contiene los elementos de diseño de nivel superior, donde ahora están los elementos de encabezado (<header>...</header>) y pie de página (<footer>...</footer>). El componente DoctorWhoLayout con el componente Episodes se representa donde aparezca @Body.
Shared/ProductionsLayout.razor:
@inherits LayoutComponentBase
<header>
<h1>Productions</h1>
</header>
<nav>
<a href="master-production-list">Master Production List</a>
<a href="production-search">Search</a>
<a href="new-production">Add Production</a>
</nav>
@Body
<footer>
Footer of Productions Layout
</footer>
El siguiente marcado HTML representado lo genera el diseño anidado anterior. El marcado extraño no se muestra para centrarnos en el contenido anidado proporcionado por los tres componentes implicados:
- Los elementos de encabezado (
<header>...</header>), barra de navegación de producción (<nav>...</nav>) y pie de página (<footer>...</footer>), y su contenido proceden del componenteProductionsLayout. - El título Doctor Who™ Episode Database (
<h1>...</h1>), la barra de navegación de episodios (<nav>...</nav>) y el elemento informativo de marca comercial (<div>...</div>) proceden del componenteDoctorWhoLayout. - El título Episodes (
<h2>...</h2>) y la lista de episodios (<ul>...</ul>) proceden del componenteEpisodes.
<body>
<div id="app">
<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>
<h1>Doctor Who™ Episode Database</h1>
<nav>
<a href="episode-main-list">Main Episode List</a>
<a href="episode-search">Search</a>
<a href="new-episode">Add Episode</a>
</nav>
<h2>Episodes</h2>
<ul>
<li>...</li>
<li>...</li>
<li>...</li>
</ul>
<div>
Doctor Who is a registered trademark of the BBC.
https://www.doctorwho.tv/
</div>
<footer>
Footer of Productions Layout
</footer>
</div>
</body>
Uso compartido de un diseño de Razor Pages con componentes integrados
Si los componentes enrutables se integran en una aplicación de Razor Pages, el diseño compartido de la aplicación se puede usar con los componentes. Para obtener más información, vea Integración y representación previa de componentes Razor de ASP.NET Core.
Recursos adicionales
Algunos elementos de la aplicación, como los menús, los mensajes de copyright y los logotipos de la empresa, suelen formar parte del diseño general de la aplicación. Colocar una copia del marcado de estos elementos en todos los componentes de una aplicación no es eficaz. Cada vez que uno de estos elementos se actualice, deberán actualizarse todos los componentes que dicho elemento use. Este método es costoso de mantener y puede dar lugar a contenido incoherente si una actualización no se lleva a cabo. Los diseños resuelven este tipo de problemas.
Un diseño de Blazor es un componente Razor que comparte el marcado con los componentes que hacen referencia a él. Los diseños pueden usar características de los componentes, como el enlace de datos y la inserción de dependencias, entre otras.
Componentes de diseño
Creación de un componente de diseño
Para crear un componente de diseño:
- Cree un componente Razor definido por una plantilla Razor o código de C#. Los componentes de diseño basados en una plantilla Razor usan la extensión de archivo
.razor, igual que cualquier otro componente Razor normal. Dado que los componentes de diseño se comparten entre los componentes de una aplicación, se suelen colocar en la carpetaSharedde la aplicación, pero pueden colocarse en cualquier ubicación a la que tengan acceso los componentes que lo usan. Por ejemplo, un diseño se puede colocar en la misma carpeta que los componentes que lo usan. - Herede el componente de LayoutComponentBase. LayoutComponentBase define una propiedad Body (de tipo RenderFragment) para el contenido representado dentro del diseño.
- Use la sintaxis
@Bodyde Razor para especificar la ubicación en el marcado de diseño donde se representa el contenido.
El siguiente componente DoctorWhoLayout muestra la plantilla Razor de un componente de diseño. El diseño hereda LayoutComponentBase y establece @Body entre la barra de navegación (<nav>...</nav>) y el pie de página (<footer>...</footer>).
Shared/DoctorWhoLayout.razor:
@inherits LayoutComponentBase
<header>
<h1>Doctor Who™ 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/";
}
Componente de MainLayout
En una aplicación creada a partir de una plantilla de proyecto de Blazor, el componente MainLayout es el diseño predeterminado de la aplicación.
Shared/MainLayout.razor:
@inherits LayoutComponentBase
<div class="sidebar">
<NavMenu />
</div>
<div class="main">
<div class="top-row px-4">
<a href="https://docs.microsoft.com/aspnet/" target="_blank">About</a>
</div>
<div class="content px-4">
@Body
</div>
</div>
Aplicación de un diseño
Aplicación de diseño a un componente
Use la directiva @layout de Razor para aplicar un diseño a un componente de Razor enrutable que tenga una directiva @page. El compilador convierte @layout en LayoutAttribute y aplica el atributo a la clase de componente.
El contenido del siguiente componente Episodes se inserta en DoctorWhoLayout en la posición @Body.
Pages/Episodes.razor:
@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>
El siguiente marcado HTML representado lo genera el componente DoctorWhoLayout anterior y el componente Episodes. El marcado extraño no se muestra para centrarnos en el contenido proporcionado por los dos componentes implicados:
- El título Doctor Who™ Episode Database (
<h1>...</h1>) del encabezado (<header>...</header>), la barra de navegación (<nav>...</nav>) y el elemento informativo de marca comercial (<div>...</div>) del pie de página (<footer>...</footer>) proceden del componenteDoctorWhoLayout. - El título Episodes (
<h2>...</h2>) y la lista de episodios (<ul>...</ul>) proceden del componenteEpisodes.
<body>
<div id="app">
<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>
<h2>Episodes</h2>
<ul>
<li>...</li>
<li>...</li>
<li>...</li>
</ul>
<footer>
Doctor Who is a registered trademark of the BBC.
https://www.doctorwho.tv/
</footer>
</div>
</body>
Al especificar el diseño directamente en un componente, se reemplaza un diseño predeterminado que:
- Se ha establecido mediante una directiva
@layoutimportada de un componente_Imports(_Imports.razor), como se describe en la sección Aplicación de un diseño a una carpeta de componentes. - Se ha establecido como el diseño predeterminado de la aplicación, como se describe en la sección Aplicación de un diseño predeterminado a una aplicación más adelante en este artículo.
Aplicación de un diseño a una carpeta de componentes
Cada una de las carpetas de una aplicación puede contener opcionalmente un archivo de plantilla denominado _Imports.razor. El compilador incluye las directivas especificadas en el archivo de importaciones de todas las plantillas de Razor de la misma carpeta y, de forma recurrente, de todas sus subcarpetas. Por lo tanto, un archivo _Imports.razor que contiene @layout DoctorWhoLayout garantiza que todos los componentes de una carpeta usen el componente DoctorWhoLayout. No es necesario agregar continuamente @layout DoctorWhoLayout a todos los componentes Razor (.razor) dentro de la carpeta y las subcarpetas.
_Imports.razor:
@layout DoctorWhoLayout
...
El archivo _Imports.razor es similar al archivo _ViewImports.cshtml de las vistas y las páginas de Razor, aunque se aplica específicamente a los archivos de componentes de Razor.
Cuando se especifica un diseño en _Imports.razor, este reemplaza el diseño especificado como diseño de la aplicación predeterminado del enrutador. Esto se describe en la siguiente sección.
Advertencia
No agregue una directiva @layout de Razor al archivo raíz _Imports.razor, que da como resultado un bucle infinito de diseños. Para controlar el diseño predeterminado de la aplicación, especifique el diseño en el componente Router. Para obtener más información, vea la sección Aplicación de un diseño predeterminado a una aplicación.
La directiva @layout de Razor únicamente aplica un diseño a los componentes Razor enrutables con una directiva @page.
Aplicación de un diseño predeterminado a una aplicación
Especifique el diseño predeterminado de la aplicación en el componente Router del componente App. En el siguiente ejemplo de una aplicación basada en una plantilla de proyecto de Blazor, el diseño predeterminado se establece en el componente MainLayout.
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>
Para obtener más información sobre el componente Router, consulte el artículo Enrutamiento de Blazor de ASP.NET Core.
Especificar el diseño como un diseño predeterminado en el componente Router es útil en el sentido de que permite reemplazar el diseño según el componente o la carpeta, como se describe en las secciones anteriores de este artículo. Se recomienda usar el componente Router para establecer el diseño predeterminado de la aplicación, ya que es el método más general y flexible de uso de diseños.
Aplicación de un diseño a contenido arbitrario (componente LayoutView)
Para establecer el diseño del contenido arbitrario de una plantilla Razor, especifique el diseño con un componente LayoutView. LayoutView se puede usar en cualquier componente Razor. En el siguiente ejemplo se establece un componente de diseño denominado ErrorLayout para la plantilla NotFound del componente MainLayout (<NotFound>...</NotFound>).
App.razor:
<Router AppAssembly="@typeof(Program).Assembly">
<Found Context="routeData">
<RouteView RouteData="@routeData" DefaultLayout="@typeof(MainLayout)" />
</Found>
<NotFound>
<LayoutView Layout="@typeof(ErrorLayout)">
<h1>Page not found</h1>
<p>Sorry, there's nothing at this address.</p>
</LayoutView>
</NotFound>
</Router>
Diseños anidados
Un componente puede hacer referencia a un diseño que, a su vez, hace referencia a otro diseño. Por ejemplo, los diseños anidados se usan para crear una estructura de menú de varios niveles.
En el ejemplo siguiente se muestra cómo usar los diseños anidados. El componente Episodes de la sección Aplicación de un diseño a un componente es el componente que se va a mostrar. El componente hace referencia al componente DoctorWhoLayout.
El siguiente componente DoctorWhoLayout es una versión modificada del ejemplo que vimos antes en este artículo. Se le han quitado los elementos de encabezado y pie de página, y el diseño hace referencia a otro diseño, ProductionsLayout. El componente Episodes se representa cuando @Body aparece en DoctorWhoLayout.
Shared/DoctorWhoLayout.razor:
@inherits LayoutComponentBase
@layout ProductionsLayout
<h1>Doctor Who™ Episode Database</h1>
<nav>
<a href="episode-masterlist">Master 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/";
}
El componente ProductionsLayout contiene los elementos de diseño de nivel superior, donde ahora están los elementos de encabezado (<header>...</header>) y pie de página (<footer>...</footer>). El componente DoctorWhoLayout con el componente Episodes se representa donde aparezca @Body.
Shared/ProductionsLayout.razor:
@inherits LayoutComponentBase
<header>
<h1>Productions</h1>
</header>
<nav>
<a href="master-production-list">Master Production List</a>
<a href="production-search">Search</a>
<a href="new-production">Add Production</a>
</nav>
@Body
<footer>
Footer of Productions Layout
</footer>
El siguiente marcado HTML representado lo genera el diseño anidado anterior. El marcado extraño no se muestra para centrarnos en el contenido anidado proporcionado por los tres componentes implicados:
- Los elementos de encabezado (
<header>...</header>), barra de navegación de producción (<nav>...</nav>) y pie de página (<footer>...</footer>), y su contenido proceden del componenteProductionsLayout. - El título Doctor Who™ Episode Database (
<h1>...</h1>), la barra de navegación de episodios (<nav>...</nav>) y el elemento informativo de marca comercial (<div>...</div>) proceden del componenteDoctorWhoLayout. - El título Episodes (
<h2>...</h2>) y la lista de episodios (<ul>...</ul>) proceden del componenteEpisodes.
<body>
<div id="app">
<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>
<h1>Doctor Who™ Episode Database</h1>
<nav>
<a href="episode-main-list">Main Episode List</a>
<a href="episode-search">Search</a>
<a href="new-episode">Add Episode</a>
</nav>
<h2>Episodes</h2>
<ul>
<li>...</li>
<li>...</li>
<li>...</li>
</ul>
<div>
Doctor Who is a registered trademark of the BBC.
https://www.doctorwho.tv/
</div>
<footer>
Footer of Productions Layout
</footer>
</div>
</body>
Uso compartido de un diseño de Razor Pages con componentes integrados
Si los componentes enrutables se integran en una aplicación de Razor Pages, el diseño compartido de la aplicación se puede usar con los componentes. Para obtener más información, vea Integración y representación previa de componentes Razor de ASP.NET Core.