Condividi tramite


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 cartella Shared o Layout 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 , vedere i componenti di ASP.NET Core.

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 nome Layout si trova all'interno di una Components 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 @layoutRazor 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 componente DoctorWhoLayout.
  • Il titolo H2 "episodi" (<h2>...</h2>) e l'elenco episodi (<ul>...</ul>) provengono dal componente Episodes.
<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:

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 @layoutRazor 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 il ProductionsLayout 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 componente DoctorWhoLayout.
  • Il titolo H2 "episodi" (<h2>...</h2>) e l'elenco degli episodi (<ul>...</ul>) provengono dal componente Episodes.
<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 , vedere le sezioni di ASP.NET Core .

Risorse aggiuntive