共用方式為


ASP.NET Core Blazor 版面配置

注意

這不是這篇文章的最新版本。 如需目前版本,請參閱本文的 .NET 8 版本

警告

不再支援此版本的 ASP.NET Core。 如需詳細資訊,請參閱 .NET 和 .NET Core 支援原則。 如需目前版本,請參閱本文的 .NET 8 版本

重要

這些發行前產品的相關資訊在產品正式發行前可能會有大幅修改。 Microsoft 對此處提供的資訊,不做任何明確或隱含的瑕疵擔保。

如需目前版本,請參閱本文的 .NET 8 版本

本文說明如何為 Blazor 應用程式建立可重複使用的版面配置元件。

Blazor 配置的實用性

某些應用程式元素 (例如功能表、著作權訊息和公司標誌) 通常是應用程式整體呈現的一部分。 將這些元素的標記複本放入應用程式的所有元件效果不彰。 每次更新其中一個專案時,都必須更新使用該元素的每個元件。 這種方法的成本很高,且如果遺漏更新,可能會導致內容不一致。 版面配置可以解決這些問題。

Blazor 版面配置是與參考該版面配置的元件共用標記的 Razor 元件。 版面配置可以使用資料繫結相依性插入,以及元件的其他功能。

版面配置元件

建立版面配置元件

若要建立版面配置元件:

  • 建立 Razor 範本或 C# 程式碼所定義的 Razor 元件。 以 Razor 範本為基礎的版面配置元件會使用 .razor 副檔名,就像一般 Razor 元件一樣。 因為配置元件會跨應用程式的元件共用,所以通常會放在應用程式的 SharedLayout 資料夾中。 不過,版面配置可以放置在可供使用該版面配置的元件進行存取的任何位置。 例如,版面配置可以放在與使用該版面配置的元件相同資料夾中。
  • LayoutComponentBase 繼承元件。 LayoutComponentBase 會定義版面配置內轉譯內容的 Body 屬性 (RenderFragment 類型)。
  • 使用 Razor 語法 @Body 來指定轉譯內容版面配置標記中的位置。

注意

如需 RenderFragment 的詳細資訊,請參閱 ASP.NET Core Razor 元件

下列 DoctorWhoLayout 元件會顯示版面配置元件的 Razor 範本。 版面配置會繼承 LayoutComponentBase 並設定導覽列 (<nav>...</nav>) 與頁尾 (<footer>...</footer>) 之間的 @Body

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 (MDN documentation) (W3C 規格)。

Blazor 的 CSS 隔離功能會將隔離的 CSS 樣式套用至 MainLayout 元件。 依照慣例,樣式是由相同名稱 (MainLayout.razor.css) 的隨附樣式表單所提供。 樣式表單的 ASP.NET Core 架構實作可在 ASP.NET Core 參考來源 (dotnet/aspnetcore GitHub 存放庫) 中進行檢查:

注意

.NET 參考來源的文件連結通常會載入存放庫的預設分支,這表示下一版 .NET 的目前開發。 若要選取特定版本的標籤,請使用 [切換分支或標籤] 下拉式清單。 如需詳細資訊,請參閱如何選取 ASP.NET Core 原始程式碼 (dotnet/AspNetCore.Docs #26205) 的版本標籤

Blazor 的 CSS 隔離功能會將隔離的 CSS 樣式套用至 MainLayout 元件。 依照慣例,樣式是由相同名稱 (MainLayout.razor.css) 的隨附樣式表單所提供。 樣式表單的 ASP.NET Core 架構實作可在 ASP.NET Core 參考來源 (dotnet/aspnetcore GitHub 存放庫) 中進行檢查:

注意

.NET 參考來源的文件連結通常會載入存放庫的預設分支,這表示下一版 .NET 的目前開發。 若要選取特定版本的標籤,請使用 [切換分支或標籤] 下拉式清單。 如需詳細資訊,請參閱如何選取 ASP.NET Core 原始程式碼 (dotnet/AspNetCore.Docs #26205) 的版本標籤

套用版面配置

讓配置命名空間可供使用

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
    

將版面配置套用至元件

使用 @layoutRazor 指示詞,將版面配置套用至具有 @page 指示詞的可路由 Razor 元件。 編譯器會將 @layout 轉換成 LayoutAttribute,並將屬性套用至元件類別。

下列 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 標記是由上述 DoctorWhoLayoutEpisodes 所產生。 無關的標記不會顯示,以便專注於所涉及兩個元件提供的內容上:

  • 標頭 (<header>...</header>) 中的 H1 "database" 標頭 (<h1>...</h1>)、導覽列 (<nav>...</nav>),以及頁尾 (<footer>...</footer>) 中來自 DoctorWhoLayout 元件的商標資訊。
  • H2 "episodes" 標題 (<h2>...</h2>) 以及來自 Episodes 元件的影集清單 (<ul>...</ul>)。
<header>
    <h1 ...>...</h1>
</header>

<nav>
    ...
</nav>

<h2>...</h2>

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

<footer>
    ...
</footer>

直接在元件中指定版面配置會覆寫預設版面配置

將版面配置套用至元件的資料夾

應用程式的每個資料夾都可以選擇性地包含名為 _Imports.razor 的範本檔案。 編譯器包含相同資料夾所有 Razor 範本的匯入檔案中所指定的指示詞,及其所有子資料夾中以遞迴方式指定的指示詞。 因此,包含 @layout DoctorWhoLayout_Imports.razor 檔案可確保資料夾中的所有元件都使用 DoctorWhoLayout 元件。 不需要重複將 @layout DoctorWhoLayout 新增至資料夾和子資料夾內的所有 Razor 元件 (.razor)。

_Imports.razor

@layout DoctorWhoLayout
...

_Imports.razor 檔案類似於 Razor 檢視和頁面的 _ViewImports.cshtml 檔案,但特別套用至 Razor 元件檔案。

_Imports.razor 中指定版面配置會覆寫指定為路由器預設應用程式版面配置的版面配置,如下一節中所述。

警告

將 Razor@layout 指示詞新增至根 _Imports.razor 檔案,這會導致版面配置無限迴圈。 若要控制預設應用程式版面配置,請在 Router 元件中指定版面配置。 如需詳細資訊,請參閱下列將預設版面配置套用至應用程式一節。

注意

@layoutRazor 指示詞只會將版面配置套用至具有 @page 指示詞的可路由 Razor 元件。

將預設版面配置套用至應用程式

Router 元件的 RouteView 元件中,指定預設的應用程式版面配置。 使用 DefaultLayout 參數來設定配置類型:

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

在上述範例中,{LAYOUT} 預留位置是配置 (例如 DoctorWhoLayout,如果配置檔案名稱是 DoctorWhoLayout.razor 的話)。 視 .NET 版本和 Blazor 應用程式的類型而定,您可能需要識別配置的命名空間。 如需詳細資訊,請參閱讓配置命名空間可供使用一節。

將配置指定為 Router 元件中 RouteView 的預設配置是實用的做法,因為您可以覆寫每一個元件或每一個資料夾的配置,如本文的前幾節所述。 我們建議使用 Router 元件來設定應用程式的預設版面配置,因為其為使用版面配置最一般且彈性的方法。

將版面配置套用至任意內容 (LayoutView 元件)

若要設定任意 Razor 範本內容的版面配置,請使用 LayoutView 元件指定版面配置。 您可以在任何 Razor 元件中使用 LayoutView。 下列範例會為 MainLayout 元件的 NotFound 範本設定名為 ErrorLayout 的版面配置 (<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>

視 .NET 版本和 Blazor 應用程式類型而定,您可能需要 identity 版面配置的命名空間。 如需詳細資訊,請參閱讓配置命名空間可供使用一節。

重要

Blazor Web App 不會使用 NotFound 參數 (<NotFound>...</NotFound> 標記),但為了回溯相容性會支援該參數,以避免架構發生重大變更。 伺服器端 ASP.NET Core 中介軟體管線會處理伺服器上的要求。 使用伺服器端技術來處理不正確的要求。 如需詳細資訊,請參閱 ASP.NET Core Blazor 轉譯模式

注意

隨著 ASP.NET Core 5.0.1 的發行以及在任何其他 5.x 版中,Router 元件會包含設定為 @truePreferExactMatches 參數。 如需詳細資訊,請參閱從 ASP.NET Core 3.1 移轉至 5.0

巢狀配置

元件可以參考接著參考另一個版面配置的版面配置。 例如,巢狀配置可用來建立多層次功能表結構。

下列範例示範如何使用巢狀配置。 [將版面配置套用至元件] 區段中顯示的 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>) 元素現在位於其中。 DoctorWhoLayoutEpisodes 元件會在 @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 標記是由上述巢狀配置所產生。 無關的標記不會顯示,以便專注於所涉及三個元件提供的巢狀內容上:

  • 標頭 (<header>...</header>)、生產導覽列 (<nav>...</nav>) 和頁尾 (<footer>...</footer>) 元素及其內容來自 ProductionsLayout 元件。
  • H1 "database" 標頭 (<h1>...</h1>)、影集導覽列 (<nav>...</nav>),以及來自 DoctorWhoLayout 元件的商標資訊 (<div>...</div>)。
  • H2 "episodes" 標題 (<h2>...</h2>) 以及來自 Episodes 元件的影集清單 (<ul>...</ul>)。
<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 應用程式時,應用程式的共用版面配置可以與元件搭配使用。 如需詳細資訊,請參閱將 ASP.NET Core Razor 元件整合至 ASP.NET Core 應用程式中

當可路由元件整合到 Razor Pages 應用程式時,應用程式的共用版面配置可以與元件搭配使用。 如需詳細資訊,請參閱預先轉譯和整合 ASP.NET Core Razor 元件

區段

若要從子 Razor 元件控制版面配置中的內容,請參閱 ASP.NET Core Blazor 小節

其他資源