頁面、路由和版面配置
提示
本內容節錄自《Blazor for ASP NET Web Forms Developers for Azure》電子書,可以從 .NET Docs 取得,也可以免費下載 PDF 離線閱讀。
ASP.NET Web Forms 應用程式是由 .aspx 檔案中定義的頁面所組成。 每個頁面的位址都是以其在專案中的實體檔案路徑為基礎。 當瀏覽器對頁面提出要求時,會在伺服器上動態轉譯頁面的內容。 該轉譯會同時處理頁面的 HTML 標記和其伺服器控制項。
在 Blazor 中,應用程式中的每個頁面都是一個元件,通常會定義於 .razor 檔案中,且具有一或多個指定的路由。 路由傳送大部分發生於用戶端,而不會涉及特定的伺服器要求。 瀏覽器會先對應用程式的根位址提出要求。 然後,Blazor 應用程式中的根 Router
元件會負責攔截瀏覽要求,並將其轉接至正確的元件。
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
會攔截瀏覽,並在路由符合位址時,使用擷取的 RouteData
來轉譯其 Found
參數的內容,否則,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 Web Forms 中的頁面配置會由主版頁面處理。 主版頁面會定義含有一或多個內容預留位置的範本,其接著可由個別頁面提供內容。 主版頁面定義於 .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>© <%: DateTime.Now.Year %> - My ASP.NET Application</p>
</footer>
</div>
</form>
</body>
</html>
在 Blazor 中,您使用配置元件來處理頁面配置。 配置元件繼承自 LayoutComponentBase
,其會定義 RenderFragment
類型的單一 Body
屬性,可用來轉譯頁面的內容。
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 元素 (<html>
、<body>
、<head>
等等)。 根 HTML 元素會改為定義於 Blazor 應用程式的主機頁面中,其可用來轉譯應用程式的初始 HTML 內容 (請參閱啟動 Blazor)。 主機頁面可以為具有周圍標記的應用程式轉譯多個根元件。
Blazor 中的元件 (包括頁面) 無法轉譯 <script>
標記。 此轉譯限制存在的原因,是因為 <script>
標記只能載入一次,接著便無法變更。 如果您嘗試使用 Razor 語法動態轉譯標記,可能就會發生非預期的行為。 相反地,所有 <script>
標記都應該新增至應用程式的主機頁面。