Diseños de ASP.NET Core Blazor
Nota
Esta no es la versión más reciente de este artículo. Para la versión actual, consulte la versión de .NET 9 de este artículo.
Advertencia
Esta versión de ASP.NET Core ya no se admite. Para obtener más información, consulte la directiva de compatibilidad de .NET y .NET Core. Para la versión actual, consulte la versión de .NET 9 de este artículo.
Importante
Esta información hace referencia a un producto en versión preliminar, el cual puede sufrir importantes modificaciones antes de que se publique la versión comercial. Microsoft no proporciona ninguna garantía, expresa o implícita, con respecto a la información proporcionada aquí.
Para la versión actual, consulte la versión de .NET 9 de este artículo.
En este artículo se explica cómo crear componentes de diseño reutilizables para aplicaciones Blazor.
Utilidad de los diseños de 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:
- Crea 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, normalmente se colocan en la carpetaShared
oLayout
de 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. - Hereda el componente de LayoutComponentBase. LayoutComponentBase define una propiedad Body (de tipo RenderFragment) para el contenido representado dentro del diseño.
- Usa la sintaxis
@Body
de Razor para especificar la ubicación en el marcado de diseño donde se representa el contenido.
Nota
Para obtener más información sobre RenderFragment, consulta Componentes de ASP.NET Core Razor.
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>
).
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 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. El diseño de Blazor adopta Flexbox layout model (MDN documentation) (especificación de W3C).
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, MainLayout.razor.css
. La implementación del marco ASP.NET Core de la hoja de estilos está disponible para su inspección en el origen de referencia de ASP.NET Core (repositorio dotnet/aspnetcore
de GitHub):
Nota
Los vínculos de la documentación al origen de referencia de .NET cargan normalmente la rama predeterminada del repositorio, que representa el desarrollo actual para la próxima versión de .NET. Para seleccionar una etiqueta de una versión específica, usa la lista desplegable Cambiar ramas o etiquetas. Para obtener más información, consulta Procedimientos para seleccionar una etiqueta de versión de código fuente de ASP.NET Core (dotnet/AspNetCore.Docs #26205).
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, MainLayout.razor.css
.
Aplicación de un diseño
Hacer que el espacio de nombres de diseño esté disponible
Las ubicaciones de los archivos de diseño y los espacios de nombres cambiaron con el tiempo para el marco Blazor. Según la versión de Blazor y el tipo de aplicación Blazor que esté compilando, es posible que tengas que indicar el espacio de nombres del diseño al usarlo. Al hacer referencia a una implementación de diseño y no se encuentre el diseño sin indicar el espacio de nombres del diseño, usa cualquiera de los métodos siguientes:
Agrega una directiva
@using
al archivo_Imports.razor
para la ubicación de los diseños. En el ejemplo siguiente, una carpeta de diseños con el nombreLayout
está dentro de una carpetaComponents
y el espacio de nombres de la aplicación esBlazorSample
:@using BlazorSample.Components.Layout
Agrega una directiva
@using
en la parte superior de la definición del componente donde se usa el diseño:@using BlazorSample.Components.Layout @layout DoctorWhoLayout
Califica completamente el espacio de nombres del diseño donde se usa:
@layout BlazorSample.Components.Layout.DoctorWhoLayout
Aplicación de diseño a un componente
Usa la directiva @layout
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
.
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>
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 "database" H1 (
<h1>...</h1>
) del encabezado (<header>...</header>
), la barra de navegación (<nav>...</nav>
) y la información de marca comercial del pie de página (<footer>...</footer>
) proceden del componenteDoctorWhoLayout
. - El título "episodes" H2 (
<h2>...</h2>
) y la lista de episodios (<ul>...</ul>
) proceden del componenteEpisodes
.
<header>
<h1 ...>...</h1>
</header>
<nav>
...
</nav>
<h2>...</h2>
<ul>
<li>...</li>
<li>...</li>
<li>...</li>
</ul>
<footer>
...
</footer>
Al especificar el diseño directamente en un componente, se reemplaza un diseño predeterminado que:
- Se establece mediante una directiva
@layout
importada desde un archivo_Imports.razor
, como se describe en la siguiente 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 agregues una directiva Razor@layout
al archivo raíz _Imports.razor
, pues da como resultado un bucle infinito de diseños. Para controlar el diseño predeterminado de la aplicación, especifica el diseño en el componente Router. Para obtener más información, consulta la sección Aplicación de un diseño predeterminado a una aplicación.
Nota
La directiva @layout
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
Especifica el diseño predeterminado de la aplicación en el componente RouteView del componente Router. Usa el parámetro DefaultLayout para establecer el tipo de diseño:
<RouteView RouteData="routeData" DefaultLayout="typeof({LAYOUT})" />
En el ejemplo anterior, el marcador de posición {LAYOUT}
es el diseño (por ejemplo, DoctorWhoLayout
si el nombre de archivo del diseño es DoctorWhoLayout.razor
). Es posible que tengas que identificar el espacio de nombres del diseño en función de la versión de .NET y el tipo de aplicación Blazor. Para obtener más información, consulta la sección Hacer que el espacio de nombres de diseño esté disponible.
Especificar el diseño como un diseño predeterminado en el RouteView del 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, especifica 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>
).
<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>
Es posible que tengas que hacer identity para el espacio de nombres del diseño en función de la versión de .NET y el tipo de aplicación Blazor. Para obtener más información, consulta la sección Hacer que el espacio de nombres de diseño esté disponible.
Importante
Los objetos Blazor Web App no usan el parámetro NotFound (marcado <NotFound>...</NotFound>
), pero el parámetro es compatible con versiones anteriores para evitar un cambio importante en el marco. La canalización de middleware del lado servidor ASP.NET procesa las solicitudes en el servidor. Usa técnicas del lado servidor para controlar las solicitudes incorrectas. Para obtener más información, consulta Modos de representación de ASP.NET CoreBlazor.
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 obtener más información, consulta 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
.
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/";
}
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
.
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>
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 "database" H1 (
<h1>...</h1>
), la barra de navegación de episodios (<nav>...</nav>
) y la información de marca comercial (<div>...</div>
) proceden del componente deDoctorWhoLayout
. - El título "episodes" H2 (
<h2>...</h2>
) y la lista de episodios (<ul>...</ul>
) proceden del 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>
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, consulte Integración de ASP.NET componentes principales Razor con MVC o Razor Pages.
Secciones
Para controlar el contenido de un diseño desde un componente Razor secundario, consulte las secciones ASP.NET Core de Blazor.