共用方式為


頁面、路由和版面配置

小提示

本內容節錄自《Blazor for ASP NET Web Forms Developers for Azure》電子書,可以從 .NET Docs 取得,也可以免費下載 PDF 離線閱讀。

Blazor-for-ASP-NET-Web-Forms-Developers 電子書封面縮圖。

ASP.NET Web Forms 應用程式是由 .aspx 檔案中定義的頁面所組成。 每個頁面的位址是以專案中的實體檔案路徑為基礎。 當瀏覽器對頁面提出要求時,頁面的內容會在伺服器上動態轉譯。 頁面的渲染同時考慮了 HTML 標記和伺服器控制項。

在 中 Blazor,應用程式中的每個頁面都是元件,通常是在 .razor 檔案中定義,並具有一或多個指定的路由。 路由主要在客戶端進行,而不需要涉及特定的伺服器請求。 瀏覽器會先對應用程式的根位址提出要求。 然後,應用程式中的Router根Blazor元件會處理攔截流覽要求,並將其轉送至正確的元件。

Blazor 也支援 深層連結。 當瀏覽器向應用程式根目錄以外的特定路由提出要求時,就會發生深層連結。 路由至伺服器的深層連結請求會轉發至 Blazor 應用程式,然後在客戶端路由至正確的元件。

ASP.NET Web Forms 中的簡單頁面可能包含下列標記:

Name.aspx

<%@ Page Title="Name" Language="C#" MasterPageFile="~/Site.Master" AutoEventWireup="true" CodeBehind="Name.aspx.cs" Inherits="WebApplication1.Name" %>

<asp:Content ID="BodyContent" ContentPlaceHolderID="MainContent" runat="server">
    <div>
        What is your name?<br />
        <asp:TextBox ID="TextBox1" runat="server"></asp:TextBox>
        <asp:Button ID="Button1" runat="server" Text="Submit" OnClick="Button1_Click" />
    </div>
    <div>
        <asp:Literal ID="Literal1" runat="server" />
    </div>
</asp:Content>

Name.aspx.cs

public partial class Name : System.Web.UI.Page
{
    protected void Button1_Click1(object sender, EventArgs e)
    {
        Literal1.Text = "Hello " + TextBox1.Text;
    }
}

應用程式中的對等頁面 Blazor 看起來會像這樣:

Name.razor

@page "/Name"
@layout MainLayout

<div>
    What is your name?<br />
    <input @bind="text" />
    <button @onclick="OnClick">Submit</button>
</div>
<div>
    @if (name != null)
    {
        @:Hello @name
    }
</div>

@code {
    string text;
    string name;

    void OnClick() {
        name = text;
    }
}

建立頁面

若要在 Blazor 中建立頁面,請建立元件,並新增 @page Razor 指令來指定元件的路由。 指令 @page 採用一個參數,即要新增至該元件的路由範本。

@page "/counter"

需要路由範本參數。 不同於 ASP.NET Web Forms,無法從其檔案位置推斷至Blazor元件的路由(雖然未來可能會新增該功能)。

路由範本語法是用於 ASP.NET Web Forms 中路由的相同基本語法。 路由參數是使用大括弧在範本中指定。 Blazor 會將路由值系結至具有相同名稱的元件參數(不區分大小寫)。

@page "/product/{id}"

<h1>Product @Id</h1>

@code {
    [Parameter]
    public string Id { get; set; }
}

您也可以指定路由參數值的條件約束。 例如,若要將產品識別碼限制為 int

@page "/product/{id:int}"

<h1>Product @Id</h1>

@code {
    [Parameter]
    public int Id { get; set; }
}

如需 所支援 Blazor之路由條件約束的完整清單,請參閱 路由條件約束

路由器元件

中的 Blazor 路由是由 Router 元件處理。 元件 Router 通常用於應用程式的根元件 (App.razor)。

<Router AppAssembly="@typeof(Program).Assembly">
    <Found Context="routeData">
        <RouteView RouteData="@routeData" DefaultLayout="@typeof(MainLayout)" />
    </Found>
    <NotFound>
        <LayoutView Layout="@typeof(MainLayout)">
            <p>Sorry, there's nothing at this address.</p>
        </LayoutView>
    </NotFound>
</Router>

元件 Router 會在指定的 AppAssembly 和選擇性的 AdditionalAssemblies中探索可路由的元件。 當瀏覽器導航時,Router會攔截導航。若路由符合位址,則以擷取的Found呈現其RouteData參數的內容;否則,Router將呈現其NotFound參數。

RouteView 元件會處理渲染 RouteData 指定的相符元件,如果該元件有配置,則會使用其布局。 如果相符的元件沒有配置版面,則會使用選擇性指定的 DefaultLayout

元件 LayoutView 會在指定的佈局中呈現其子內容。 我們將在本章稍後更詳細地查看版面配置。

在 ASP.NET Web Forms 中,您會將重新導向回應傳回至瀏覽器,以觸發流覽至不同的頁面。 例如:

protected void NavigateButton_Click(object sender, EventArgs e)
{
    Response.Redirect("Counter");
}

通常無法在Blazor中傳回重新導向回應。 Blazor 不會使用要求-回復模型。 不過,您可以直接觸發瀏覽器流覽,就像使用 JavaScript 一樣。

Blazor提供的NavigationManager服務可用來:

  • 取得目前的瀏覽器位址
  • 取得基位址
  • 觸發導航
  • 在地址變更時收到通知

若要瀏覽至不同的位址,請使用 NavigateTo 方法:

@page "/"
@inject NavigationManager NavigationManager

<button @onclick="Navigate">Navigate</button>

@code {
    void Navigate() {
        NavigationManager.NavigateTo("counter");
    }
}

如需所有 NavigationManager 成員的描述,請參閱 URI 和導覽狀態協助程式

基底 URL

Blazor如果您的應用程式部署在基底路徑下,則必須使用<base>標籤在頁面元數據中指定基底 URL,以便路由傳送至工作屬性。 如果應用程式的主機頁面是使用 Razor 進行伺服器轉譯,您可以使用 ~/ 語法來指定應用程式的基位址。 如果主機頁面是靜態 HTML,則您必須明確指定基底 URL。

<base href="~/" />

頁面配置

ASP.NET 網頁窗體中的版面配置是由主版頁面處理。 主版頁面定義了一個範本,該範本包含一或多個內容佔位元,以便由各個頁面來填入內容。 主版頁面定義於 .master 檔案中,並以 指示詞開頭 <%@ Master %>.master 檔案的內容會以您編寫.aspx頁面的方式進行編碼,但會新增<asp:ContentPlaceHolder>控制項來標記頁面可以提供內容的位置。

Site.master

<%@ Master Language="C#" AutoEventWireup="true" CodeBehind="Site.master.cs" Inherits="WebApplication1.SiteMaster" %>

<!DOCTYPE html>
<html lang="en">
<head runat="server">
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title><%: Page.Title %> - My ASP.NET Application</title>
    <link href="~/favicon.ico" rel="shortcut icon" type="image/x-icon" />
</head>
<body>
    <form runat="server">
        <div class="container body-content">
            <asp:ContentPlaceHolder ID="MainContent" runat="server">
            </asp:ContentPlaceHolder>
            <hr />
            <footer>
                <p>&copy; <%: DateTime.Now.Year %> - My ASP.NET Application</p>
            </footer>
        </div>
    </form>
</body>
</html>

在 Blazor,您可以使用版面配置元件來處理頁面佈局。 版面配置元件繼承自 LayoutComponentBase,該元件定義了一個Body屬性,其類型為RenderFragment,可用於呈現頁面的內容。

MainLayout.razor

@inherits LayoutComponentBase
<h1>Main layout</h1>
<div>
    @Body
</div>

轉譯具有版面配置的頁面時,頁面會在配置呈現其 Body 屬性所在位置的指定版面配置內容中轉譯。

若要將版面配置套用至頁面,請使用 @layout 指示詞:

@layout MainLayout

您可以使用 _Imports.razor 檔案,指定資料夾和子資料夾中所有元件的版面配置。 您也可以使用 路由器元件,為所有頁面指定預設版面配置。

主版頁面可以定義多個內容佔位元,但Blazor 中的版面配置只有一個Body 屬性。 此版面 Blazor 配置元件的限制有望在未來版本中解決。

ASP.NET Web Forms 中的主版頁面可以是巢狀的。 也就是說,一個主版頁面可以使用另一個主版頁面。 中的 Blazor 版面配置元件也可能是巢狀的。 您可以將佈局元件套用至佈局元件。 內部配置的內容將會在外部配置內呈現。

ChildLayout.razor

@layout MainLayout
<h2>Child layout</h2>
<div>
    @Body
</div>

Index.razor

@page "/"
@layout ChildLayout
<p>I'm in a nested layout!</p>

接著,頁面的轉譯輸出會是:

<h1>Main layout</h1>
<div>
    <h2>Child layout</h2>
    <div>
        <p>I'm in a nested layout!</p>
    </div>
</div>

中的Blazor版面配置通常不會定義頁面 (<html><body><head>、 等) 的根 HTML 元素。 根 HTML 元素會改為定義在 Blazor 應用程式的主機頁面中,用來轉譯應用程式的初始 HTML 內容(請參閱 Bootstrap Blazor)。 宿主頁面可以渲染具有包圍標記的應用程式的多個根元件。

中的 Blazor元件,包括頁面,無法轉譯 <script> 標籤。 此轉譯限制存在,因為 <script> 標籤載入一次,然後無法變更。 如果您嘗試使用Razor語法動態轉譯標記,可能會發生非預期的行為。 相反地,所有 <script> 標籤都應該新增至應用程式的主機頁面。