次の方法で共有


ASP.NET Core Blazor レイアウト

これは、この記事の最新バージョンではありません。 現在のリリースについては、 この記事の .NET 10 バージョンを参照してください。

警告

このバージョンの ASP.NET Core はサポート対象から除外されました。 詳細については、 .NET および .NET Core サポート ポリシーを参照してください。 現在のリリースについては、 この記事の .NET 10 バージョンを参照してください。

この記事では、Blazor アプリの再利用可能レイアウト コンポーネントの作成方法について説明します。

Blazor レイアウトの有用性

メニュー、著作権メッセージ、会社のロゴなどの一部のアプリ要素は、通常、アプリの全体的なプレゼンテーションの一部です。 これらの要素のマークアップのコピーをアプリのすべてのコンポーネントに配置するのは、効率的ではありません。 これらの要素のいずれかが更新されるたびに、その要素が使用されているすべてのコンポーネントを更新する必要があります。 この方法は維持するのにコストがかかり、更新が行われなかった場合にコンテンツの一貫性が失われるおそれがあります。 レイアウト を使用して、これらの問題を解決します。

Blazor レイアウトとは、それを参照するコンポーネントとマークアップを共有する Razor コンポーネントのことです。 レイアウトでは、データ バインディング依存関係の挿入、およびコンポーネントのその他の機能を使用できます。

レイアウト コンポーネントを作成する

レイアウト コンポーネントを作成するには:

  • Razor テンプレートまたは C# コードによって定義された Razor コンポーネントを作成します。 Razor テンプレートが基になっているレイアウト コンポーネントでは、通常の .razor コンポーネントと同じように Razor ファイル拡張子が使用されます。 レイアウト コンポーネントはアプリのコンポーネント間で共有されるため、通常はアプリの Shared または Layout フォルダーに配置されます。 ただし、レイアウトは、それを使用するコンポーネントにアクセスできる任意の場所に配置できます。 たとえば、それを使用するコンポーネントと同じフォルダーに、レイアウトを配置できます。
  • コンポーネントを LayoutComponentBase から継承します。 LayoutComponentBase によって、レイアウト内にレンダリングされるコンテンツの Body プロパティ (RenderFragment 型) が定義されています。
  • Razor 構文 @Body を使用して、コンテンツがレンダリングされるレイアウト マークアップ内の場所を指定します。

RenderFragment の詳細については、ASP.NET Core Razor コンポーネントに関する記事を参照してください。

次の DoctorWhoLayout コンポーネントには、レイアウト コンポーネント Razor テンプレートが示されています。 レイアウトにより LayoutComponentBase が継承されて、ナビゲーション バー (@Body) とフッター (<nav>...</nav>) の間に <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/";
}

MainLayout コンポーネント

Blazor プロジェクト テンプレートから作成されたアプリでは、MainLayout コンポーネントがアプリの既定のレイアウトです。 Blazor のレイアウトでは Flexbox layout model (W3C 仕様) を採用しています。

Blazor の CSS 分離機能により、分離された CSS スタイルが MainLayout コンポーネントに適用されます。 慣例により、スタイルは同じ名前 MainLayout.razor.css の付随するスタイルシートによって提供されます。 スタイルシートの ASP.NET Core フレームワークの実装を、ASP.NET Core 参照ソース (dotnet/aspnetcore GitHub リポジトリ) での検査に使用できます。

  • Blazor Web App: プロジェクト テンプレート内のサーバー プロジェクトのMainLayout.razor.cssフォルダーでComponents/Layoutを探します。
  • Blazor WebAssembly MainLayout.razor.css

通常、.NET 参照ソースへのドキュメント リンクを使用すると、リポジトリの既定のブランチが読み込まれます。このブランチは、.NET の次回リリースに向けて行われている現在の開発を表します。 特定のリリースのタグを選択するには、[Switch branches or tags](ブランチまたはタグの切り替え) ドロップダウン リストを使います。 詳細については、「ASP.NET Core ソース コードのバージョン タグを選択する方法」 (dotnet/AspNetCore.Docs #26205) を参照してください。

Blazor の CSS 分離機能により、分離された CSS スタイルが MainLayout コンポーネントに適用されます。 慣例により、スタイルは同じ名前 MainLayout.razor.css の付随するスタイルシートによって提供されます。

静的にレンダリングされたレイアウト コンポーネント

Blazor Web Appがページ単位/コンポーネントごとのレンダリングを採用する場合 (Routes コンポーネントは対話型レンダリング モードを指定しません)、レイアウト コンポーネントはサーバー上で静的にレンダリングされます。 対話型レンダリング モードをレイアウトに直接適用することはサポートされていません。 Blazor では、ルート コンポーネント パラメーターとして RenderFragment (この場合は@Body ) のシリアル化がサポートされていないためです。 たとえば、@rendermode InteractiveServer コンポーネントの上部にMainLayoutを配置すると、次のランタイム例外が発生します。

System.InvalidOperationException: rendermode 'InteractiveServerRenderMode' を使用して、パラメーター 'Body' をコンポーネント 'MainLayout' に渡すことはできません。 これは、パラメーターがデリゲート型 'Microsoft.AspNetCore.Components.RenderFragment' であるためです。これは任意のコードであり、シリアル化できません。

これは、ページ単位/コンポーネントごとのレンダリングを採用するアプリの LayoutComponentBase から継承するすべてのレイアウト コンポーネントに適用されます。

このシナリオは、 Blazorの将来のリリースで対処される可能性があります。 詳細については、「 [Blazor] SSR からのレンダー フラグメントのシリアル化のサポート (dotnet/aspnetcore #52768)」を参照してください。 それまでの間、ページ単位/コンポーネントごとのレンダリングを採用する Blazor Web App では、次のアプローチを採用できます。

対話機能が可能なラッパー コンポーネントを作成します。 次の例では、ラッパー コンポーネントに、子コンポーネントからコンテンツを受信できる Blazor セクション が含まれています。

_Imports.razor ファイルで、セクション (@using) のMicrosoft.AspNetCore.Components.Sections ディレクティブを追加します。

@using Microsoft.AspNetCore.Components.Sections

Pages フォルダーに次の対話型ラッパー コンポーネントを作成します。

Pages/InteractiveWrapper.razor:

@rendermode InteractiveServer

<div>
    <SectionOutlet SectionName="top-bar" />
</div>

@ChildContent

@code {
    [Parameter]
    public RenderFragment? ChildContent { get; set; }
}

Counter コンポーネントでは、ラッパー コンポーネントを使用し、対話型のセクション コンテンツを設定できます。 次の例では、セクションにカウンター ボタンが配置されています。

Pages/Counter.razor:

@page "/counter"
@rendermode InteractiveServer

<InteractiveWrapper>

    <SectionContent SectionName="top-bar">
        <button class="btn btn-primary" @onclick="IncrementCount">Click me</button>
    </SectionContent>

    <PageTitle>Counter</PageTitle>

    <h1>Counter</h1>

    <p role="status">Current count: @currentCount</p>

    <button class="btn btn-primary" @onclick="IncrementCount">Click me</button>

</InteractiveWrapper>

@code {
    private int currentCount = 0;

    private void IncrementCount()
    {
        currentCount++;
    }
}

アプリの周囲の他のコンポーネントは、 InteractiveWrapper コンポーネント内のコンテンツをラップし、対話型のセクション コンテンツを設定することもできます。

レイアウトを適用する

レイアウト名前空間を利用可能にする

レイアウト ファイルの場所と名前空間は、Blazor フレームワークの時間の経過に伴って変更されてきました。 ビルドしているアプリの Blazor バージョンと Blazor の種類によっては、レイアウトの名前空間を使用するときに指定する必要がある場合があります。 レイアウトの実装を参照していて、レイアウトの名前空間の表示がなく、レイアウトが見つからない場合は、次のいずれかの方法を実行します。

  • レイアウトの場所の @using ディレクティブを _Imports.razor ファイルに追加します。 次の例では、Layout という名前が付いたレイアウトのフォルダーが Components フォルダー内にあり、アプリの名前空間は BlazorSample です。

    @using BlazorSample.Components.Layout
    
  • レイアウトが使用されるコンポーネント定義の先頭に @using ディレクティブを追加します。

    @using BlazorSample.Components.Layout
    @layout DoctorWhoLayout
    
  • レイアウトが使用される名前空間を完全に修飾します。

    @layout BlazorSample.Components.Layout.DoctorWhoLayout
    

コンポーネントにレイアウトを適用する

@layout ディレクティブが使用されているルーティング可能な Razor コンポーネントにレイアウトを適用するには、Razor@page ディレクティブを使用します。 コンパイラにより、@layoutLayoutAttribute に変換され、その属性がコンポーネント クラスに適用されます。

次の Episodes コンポーネントの内容が、DoctorWhoLayout の位置にある @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>

レンダリングされた次の HTML マークアップが、前の DoctorWhoLayout および Episodes コンポーネントによって生成されます。 関連する 2 つのコンポーネントによって提供されるコンテンツに注目するため、余分なマークアップは示されていません。

  • ヘッダー (<h1>...</h1>) の H1 "database" という見出し (<header>...</header>)、ナビゲーション バー (<nav>...</nav>)、フッター (<footer>...</footer>) の商標情報は、DoctorWhoLayout コンポーネントから生成されます。
  • H2 "episodes" という見出し (<h2>...</h2>) とエピソードの一覧 (<ul>...</ul>) は、Episodes コンポーネントから生成されます。
<header>
    <h1 ...>...</h1>
</header>

<nav>
    ...
</nav>

<h2>...</h2>

<ul>
    <li>...</li>
    <li>...</li>
    <li>...</li>
</ul>

<footer>
    ...
</footer>

コンポーネントでレイアウトを直接指定すると、"既定のレイアウト" がオーバーライドされます。

  • @layout」セクションで説明されているように、_Imports.razor ファイルからインポートされた ディレクティブによって設定されます。
  • アプリの既定のレイアウトとして設定します。後の「アプリに既定のレイアウトを適用する」セクションの説明を参照してください。

レイアウトをコンポーネントのフォルダーに適用する

アプリのすべてのフォルダーには、必要に応じて、_Imports.razor という名前のテンプレート ファイルを格納できます。 コンパイラにより、インポート ファイルに指定されたディレクティブが、同じフォルダー内とそのすべてのサブフォルダー内で再帰的にすべての Razor テンプレートに含まれます。 そのため、_Imports.razor が含まれる @layout DoctorWhoLayout ファイルにより、フォルダー内のすべてのコンポーネントで DoctorWhoLayout コンポーネントが確実に使用されます。 フォルダーとサブフォルダー内のすべての @layout DoctorWhoLayout コンポーネント (Razor) に、.razor を繰り返し追加する必要はありません。

_Imports.razor:

@layout DoctorWhoLayout
...

_Imports.razor ファイルは、Razor ビューおよびページに対する _ViewImports.cshtml ファイルに似ていますが、Razor コンポーネント ファイルに限定して適用されます。

_Imports.razor でレイアウトを指定すると、ルーターの既定のアプリ レイアウトとして指定されているレイアウトがオーバーライドされます。これについては、次のセクションで説明します。

警告

ルートファイルにRazor@layoutディレクティブを追加しないでください。これによりレイアウトが無限ループになります。 既定のアプリ レイアウトを制御するには、Router コンポーネントでレイアウトを指定します。 詳細については、次の「アプリに既定のレイアウトを適用する」セクションを参照してください。

_Imports.razor ファイルを使用して、@layout ディレクティブを持つコンポーネントのフォルダーにレイアウトを適用し、レイアウト コンポーネント自体が _Imports.razor ファイルの同じフォルダーまたはフォルダー階層にある場合も、同じ条件が発生します。 @layout ディレクティブがレイアウト コンポーネントにも適用されるため、レイアウトを適用する無限ループが発生します。 再帰の問題を回避するには、レイアウト コンポーネントを独自のフォルダー (Layoutsなど) に格納し、_Imports.razor ファイルが適用されている場所から離しておくことをお勧めします。

@layout Razor ディレクティブによってレイアウトが適用されるのは、Razor ディレクティブが使用されているルーティング可能な @page コンポーネントのみです。

アプリに既定のレイアウトを適用する

Router コンポーネントの RouteView コンポーネントで、既定のアプリ レイアウトを指定します。 DefaultLayout パラメータを使用してレイアウトの種類を設定します。

<RouteView RouteData="routeData" DefaultLayout="typeof({LAYOUT})" />

前の例では、{LAYOUT} プレースホルダーがレイアウトになります (例: レイアウト ファイル名が DoctorWhoLayout の場合、DoctorWhoLayout.razor)。 .NET のバージョンとアプリの種類によっては、レイアウトの名前空間 Blazor 識別する必要がある場合があります。 詳細については、「レイアウトの名前空間を使用可能にする」セクションを参照してください。

Router コンポーネントの RouteView で既定のレイアウトとしてレイアウトを指定することは、この記事のこれまでのセクションで説明したように、コンポーネントごとまたはフォルダーごとにレイアウトをオーバーライドできるため、便利な方法です。 レイアウトを使用する最も一般的で柔軟な方法であるため、Router コンポーネントを使用してアプリの既定のレイアウトを設定することをお勧めします。

任意のコンテンツにレイアウトを適用する (LayoutView コンポーネント)

任意の Razor テンプレート コンテンツにレイアウトを設定するには、LayoutView コンポーネントでレイアウトを指定します。 LayoutView は、任意の Razor コンポーネントで使用できます。 次の例では、次のErrorLayoutマークアップを含むコンポーネントのRazorという名前のレイアウト コンポーネントを設定します。

<LayoutView Layout="typeof(ErrorLayout)">
    <h1>Page not found</h1>
    <p>Sorry, there's nothing at this address.</p>
</LayoutView>

.NET のバージョンとアプリの種類によっては、レイアウトの名前空間 Blazor 識別する必要がある場合があります。 詳細については、「レイアウトの名前空間を使用可能にする」セクションを参照してください。

.NET 5.0.1 のリリースおよび追加の 5.x リリースでは、Router コンポーネントには、PreferExactMatchesに設定された @true パラメーターが含まれます。 詳細については、「 ASP.NET Core 3.1 から .NET 5 への移行」を参照してください。

入れ子になったレイアウト

コンポーネントはレイアウトを参照でき、そのレイアウトはさらに別のレイアウトを参照できます。 たとえば、複数レベルのメニュー構造を作成するために、入れ子になったレイアウトを使用します。

次の例に、入れ子になったレイアウトの使用方法を示しています。 「Episodes」セクションで示されている コンポーネントは、表示するコンポーネントです。 そのコンポーネントで、DoctorWhoLayout コンポーネントが参照されています。

次の DoctorWhoLayout コンポーネントは、この記事の前の方で示した例を変更したバージョンです。 ヘッダー要素とフッター要素が削除され、レイアウトで別のレイアウト ProductionsLayout が参照されています。 Episodes コンポーネントは、@Body 内の 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/";
}

ProductionsLayout コンポーネントには最上位レベルのレイアウト要素が含まれ、現在はそこにヘッダー要素 (<header>...</header>) とフッター要素 (<footer>...</footer>) が存在します。 DoctorWhoLayout コンポーネントが含まれる Episodes は、@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>

レンダリングされた次の HTML マークアップが、前の入れ子になったレイアウトによって生成されます。 関連する 3 つのコンポーネントによって提供される入れ子になったコンテンツに注目するため、余分なマークアップは示されていません。

  • ヘッダー (<header>...</header>)、プロダクション ナビゲーション バー (<nav>...</nav>)、フッター (<footer>...</footer>) の各要素とその内容は、ProductionsLayout コンポーネントから生成されます。
  • H1 "database" という見出し (<h1>...</h1>)、エピソード ナビゲーション バー (<nav>...</nav>)、商標情報 (<div>...</div>) は、DoctorWhoLayout コンポーネントから生成されます。
  • H2 "episodes" という見出し (<h2>...</h2>) とエピソードの一覧 (<ul>...</ul>) は、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>

Razor Pages レイアウトを統合コンポーネントと共有する

ルーティング可能なコンポーネントが Razor Pages アプリに統合されている場合、コンポーネントでアプリの共有レイアウトを使用できます。 詳細については、「MVC または Razor Pages を使用したコア Razor コンポーネント ASP.NET 統合を参照してください。

セクション

子 Razor コンポーネントからレイアウト内のコンテンツを制御するには、「ASP.NET Core Blazor セクション」を参照してください。

その他のリソース