Layout di ASP.NET Core Blazor
Nota
Questa non è la versione più recente di questo articolo. Per la versione corrente, vedere la versione .NET 9 di questo articolo.
Avviso
Questa versione di ASP.NET Core non è più supportata. Per altre informazioni, vedere i criteri di supporto di .NET e .NET Core. Per la versione corrente, vedere la versione .NET 9 di questo articolo.
Importante
Queste informazioni si riferiscono a un prodotto non definitive che può essere modificato in modo sostanziale prima che venga rilasciato commercialmente. Microsoft non riconosce alcuna garanzia, espressa o implicita, in merito alle informazioni qui fornite.
Per la versione corrente, vedere la versione .NET 9 di questo articolo.
Questo articolo illustra come creare componenti di layout riutilizzabili per Blazor le app.
Utilità dei Blazor layout
Alcuni elementi dell'app, ad esempio menu, messaggi di copyright e logo aziendali, fanno in genere parte della presentazione complessiva dell'app. L'inserimento di una copia del markup per questi elementi in tutti i componenti di un'app non è efficiente. Ogni volta che uno di questi elementi viene aggiornato, ogni componente che utilizza l'elemento deve essere aggiornato. Questo approccio è costoso da gestire e può causare contenuti incoerenti se un aggiornamento non è stato eseguito. I layout risolvono questi problemi.
Un Blazor layout è un Razor componente che condivide il markup con i componenti che vi fanno riferimento. I layout possono usare l'associazione dati, l'iniezione delle dipendenze e altre funzionalità dei componenti.
Componenti di layout
Creare un componente di layout
Per creare un componente di layout:
- Creare un Razor componente definito da un modello o da codice Razor C#. I componenti di layout basati su un Razor modello usano l'estensione
.razor
di file esattamente come i componenti ordinari Razor . Poiché i componenti di layout vengono condivisi tra i componenti di un'app, vengono in genere inseriti nella cartellaShared
oLayout
dell'app. Tuttavia, i layout possono essere posizionati in qualsiasi posizione accessibile ai componenti che lo usano. Ad esempio, un layout può essere inserito nella stessa cartella dei componenti che lo usano. - Eredita il componente da LayoutComponentBase. LayoutComponentBase definisce una Body proprietà (RenderFragment tipo) per il contenuto sottoposto a rendering all'interno del layout.
- Usare la Razor sintassi
@Body
per specificare il percorso nel markup di layout in cui viene eseguito il rendering del contenuto.
Nota
Per ulteriori informazioni su
Il componente seguente DoctorWhoLayout
mostra il Razor modello di un componente di layout. Il layout eredita LayoutComponentBase e imposta l'oggetto @Body
tra la barra di spostamento (<nav>...</nav>
) e il piè di pagina (<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
In un'app creata da un Blazor modello di progetto, il MainLayout
componente è il layout predefinito dell'app.
BlazorIl layout adotta la Flexbox layout model (specifica W3C).
BlazorLa funzionalità di isolamento CSS applica stili CSS isolati al MainLayout
componente. Per convenzione, gli stili vengono forniti dal foglio di stile a fianco con lo stesso nome, MainLayout.razor.css
. L'implementazione del foglio di stile nel framework ASP.NET Core è disponibile per l'esame nell'origine di riferimento ASP.NET Core (dotnet/aspnetcore
repository GitHub):
Nota
I collegamenti della documentazione al codice sorgente della documentazione .NET in genere caricano il ramo predefinito del repository, che rappresenta lo sviluppo corrente per la versione successiva di .NET. Per selezionare un tag per una versione specifica, utilizzare il menu a tendina Switch branches or tags. Per altre informazioni, vedere How to select a version tag of ASP.NET Core source code (dotnet/AspNetCore.Docs #26205) (Come selezionare un tag di versione del codice sorgente di ASP.NET - dotnet/AspNetCore.Docs #26205).
BlazorLa funzionalità di isolamento CSS applica stili CSS isolati al MainLayout
componente. Per convenzione, gli stili vengono forniti dal foglio di stile a fianco con lo stesso nome, MainLayout.razor.css
.
Applicare un layout
Rendere disponibile lo spazio dei nomi del layout
I percorsi e gli spazi dei nomi dei file di layout sono stati modificati nel tempo per il Blazor framework. A seconda della versione di Blazor e del tipo di Blazor app che si sta creando, potrebbe essere necessario indicare lo spazio dei nomi del layout quando lo si usa. Quando si fa riferimento a un'implementazione di layout e il layout non viene trovato senza specificare lo spazio dei nomi del layout, adottare uno degli approcci seguenti:
Aggiungere una
@using
direttiva al file_Imports.razor
per la posizione dei layout. Nell'esempio seguente una cartella di layout con il nomeLayout
si trova all'interno di unaComponents
cartella e lo spazio dei nomi dell'app èBlazorSample
:@using BlazorSample.Components.Layout
Aggiungere una
@using
direttiva nella parte superiore della definizione del componente in cui viene usato il layout:@using BlazorSample.Components.Layout @layout DoctorWhoLayout
Qualificare completamente lo spazio dei nomi del layout dove viene utilizzato.
@layout BlazorSample.Components.Layout.DoctorWhoLayout
Applicare un layout a un componente
Utilizzare la direttiva @layout
Razor per applicare un layout a un componente instradabile Razor con una direttiva @page
. Il compilatore converte @layout
in e LayoutAttribute applica l'attributo alla classe component.
Il contenuto del componente seguente Episodes
viene inserito nell'oggetto DoctorWhoLayout
nella posizione di @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>
Il seguente markup HTML reso è prodotto dal componente DoctorWhoLayout
e Episodes
precedenti. Il markup estraneo non viene visualizzato per concentrarsi sul contenuto fornito dai due componenti coinvolti:
- L'intestazione H1 "database" (
<h1>...</h1>
) nell'intestazione (<header>...</header>
), la barra di spostamento (<nav>...</nav>
) e le informazioni sul marchio nel piè di pagina (<footer>...</footer>
) provengono dal componenteDoctorWhoLayout
. - Il titolo H2 "episodi" (
<h2>...</h2>
) e l'elenco episodi (<ul>...</ul>
) provengono dal componenteEpisodes
.
<header>
<h1 ...>...</h1>
</header>
<nav>
...
</nav>
<h2>...</h2>
<ul>
<li>...</li>
<li>...</li>
<li>...</li>
</ul>
<footer>
...
</footer>
Se si specifica il layout direttamente in un componente, viene eseguito l'override di un layout predefinito:
- Impostato da una
@layout
direttiva importata da un_Imports.razor
file, come descritto nella seguente sezione Applicare un layout a una cartella di componenti. - Impostare come layout predefinito dell'app, come descritto nella sezione Applicare un layout predefinito a un'app più avanti in questo articolo.
Applicare un layout a una cartella di componenti
Ogni cartella di un'app può facoltativamente contenere un file modello denominato _Imports.razor
. Il compilatore include le direttive specificate nel file imports in tutti i Razor modelli nella stessa cartella e in modo ricorsivo in tutte le relative sottocartelle. Pertanto, un _Imports.razor
file contenente @layout DoctorWhoLayout
garantisce che tutti i componenti di una cartella usino il DoctorWhoLayout
componente. Non è necessario aggiungere @layout DoctorWhoLayout
ripetutamente a tutti i Razor componenti (.razor
) all'interno della cartella e delle sottocartelle.
_Imports.razor
:
@layout DoctorWhoLayout
...
Il _Imports.razor
file è simile al file _ViewImports.cshtml per Razor le visualizzazioni e le pagine , ma applicato in modo specifico ai Razor file del componente.
Specificando un layout in _Imports.razor
viene eseguito l'override di un layout specificato come layout predefinito dell'app del router, descritto nella sezione seguente.
Avviso
Non aggiungere una Razor@layout
direttiva al file radice _Imports.razor
, che comporta un ciclo infinito di layout. Per controllare il layout predefinito dell'app, specificare il layout nel Router componente. Per altre informazioni, vedere la sezione Applicare un layout predefinito a un'app .
La stessa condizione si verifica quando si utilizza un file _Imports.razor
per applicare un layout a una cartella di componenti con la direttiva @layout
e il componente di layout stesso si trova nella stessa cartella o gerarchia di cartelle del file _Imports.razor
. Si verifica un ciclo infinito di applicazione del layout perché la direttiva @layout
viene applicata anche al componente di layout. Per evitare problemi di ricorsione, è consigliabile archiviare i componenti di layout nella propria cartella (ad esempio, Layouts
), lontano da dove vengono applicati _Imports.razor
file.
Nota
La direttiva @layout
Razor si applica solo ai componenti Razor instradabili che hanno una direttiva @page
.
Applicare un layout predefinito a un'app
Specificare il layout predefinito dell'app nel componente Router di RouteView. Usare il DefaultLayout parametro per impostare il tipo di layout:
<RouteView RouteData="routeData" DefaultLayout="typeof({LAYOUT})" />
Nell'esempio precedente il {LAYOUT}
segnaposto è il layout ( ad esempio, DoctorWhoLayout
se il nome del file di layout è DoctorWhoLayout.razor
). Potrebbe essere necessario identificare lo spazio dei nomi del layout in base alla versione di .NET e al tipo di Blazor app. Per ulteriori informazioni, vedere la sezione Rendere disponibile lo spazio dei nomi del layout.
Specificare il layout come layout predefinito nel Router componente è una procedura utile perché è possibile eseguire l'override RouteView del layout per ogni componente o per cartella, come descritto nelle sezioni precedenti di questo articolo. È consigliabile usare il Router componente per impostare il layout predefinito dell'app perché è l'approccio più generale e flessibile per l'uso dei layout.
Applicare un layout al componente di contenuto arbitrario (LayoutView
)
Per impostare un layout per il contenuto arbitrario Razor del modello, specificare il layout con un LayoutView componente. È possibile usare un oggetto LayoutView in qualsiasi Razor componente. Nell'esempio seguente viene impostato un componente di layout denominato ErrorLayout
per il MainLayout
modello del NotFound componente (<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>
Potrebbe essere necessario identificare il namespace del layout a seconda della versione di .NET e del tipo di app Blazor. Per ulteriori informazioni, vedere la sezione Rendere disponibile lo spazio dei nomi del layout.
Importante
Blazor Web Apps non utilizzano il parametro NotFound (<NotFound>...</NotFound>
markup), ma il parametro è supportato per la compatibilità con le versioni precedenti per evitare un cambiamento significativo nel framework. La pipeline del middleware di ASP.NET Core sul lato server elabora le richieste sul server. Usare tecniche lato server per gestire richieste non valide. Per ulteriori informazioni, vedere modalità di rendering di ASP.NET CoreBlazor.
Nota
Con la versione di ASP.NET Core 5.0.1 e per eventuali versioni 5.x aggiuntive, il componente Router
include il parametro PreferExactMatches
impostato su @true
. Per altre informazioni, vedere Eseguire la migrazione da ASP.NET Core 3.1 a 5.0.
Layout annidati
Un componente può fare riferimento a un layout che a sua volta fa riferimento a un altro layout. Ad esempio, i layout annidati vengono usati per creare strutture di menu multilivello.
Nell'esempio seguente viene illustrato come usare layout annidati. Il Episodes
componente illustrato nella sezione Applica un layout a un componente è il componente da visualizzare. Il componente fa riferimento al DoctorWhoLayout
componente.
Il componente seguente DoctorWhoLayout
è una versione modificata dell'esempio illustrato in precedenza in questo articolo. Gli elementi dell'intestazione e del piè di pagina vengono rimossi e il layout fa riferimento a un altro layout, ProductionsLayout
. Il componente Episodes
è reso dove @Body
appare nel 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/";
}
Il componente ProductionsLayout
contiene gli elementi di layout di primo livello, all'interno del quale si trovano gli elementi di header (<header>...</header>
) e di piè di pagina (<footer>...</footer>
). Il DoctorWhoLayout
con il componente Episodes
viene eseguito dove appare @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>
Il markup HTML sottoposto a rendering seguente viene prodotto dal layout annidato precedente. Il markup estraneo non viene visualizzato per concentrarsi sul contenuto annidato fornito dai tre componenti coinvolti:
- L'intestazione (
<header>...</header>
), la barra di spostamento di produzione (<nav>...</nav>
) e gli elementi piè di pagina (<footer>...</footer>
) e ilProductionsLayout
relativo contenuto provengono dal componente. - L'intestazione H1 "database" (
<h1>...</h1>
), la barra di navigazione dell'episodio (<nav>...</nav>
) e le informazioni sul marchio (<div>...</div>
) provengono dal componenteDoctorWhoLayout
. - Il titolo H2 "episodi" (
<h2>...</h2>
) e l'elenco degli episodi (<ul>...</ul>
) provengono dal 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>
Condividere un Razor layout di pagine con componenti integrati
Quando i componenti instradabili sono integrati in un'app Razor Pages, il layout condiviso dell'app può essere usato con i componenti. Per altre informazioni, vedere Integrare ASP.NET componenti Core Razor con MVC o Razor Pages.
Sezioni
Per controllare il contenuto in un layout da un componente figlio