ASP.NET Web 窗体应用由 .aspx 文件中定义的页面组成。 每个页面的地址都基于项目中的物理文件路径。 当浏览器向页面发出请求时,页面的内容将在服务器上动态呈现。 渲染同时考虑了页面的 HTML 标记及其服务器控件。
在 Blazor应用中,每个页面都是一个组件,通常在 .razor 文件中定义,其中包含一个或多个指定的路由。 路由主要发生在客户端,而无需涉及特定的服务器请求。 浏览器首先向应用的根地址发出请求。 然后,应用中的Router
根Blazor组件处理截获导航请求并将其转发到正确的组件。
Blazor 还支持 深层链接。 当浏览器向应用根目录以外的特定路由发出请求时,将发生深层链接。 发送到服务器的深层链接请求将路由到 Blazor 应用,然后将请求客户端路由到正确的组件。
ASP.NET Web 窗体中的简单页面可能包含以下标记:
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 窗体不同,Blazor从其文件位置推断到组件的路由(尽管这可能是将来添加的功能)。
路由模板语法是用于在 ASP.NET Web 窗体中路由的相同基本语法。 使用大括号在模板中指定路由参数。 Blazor 将路由值绑定到具有相同名称的组件参数(不区分大小写)。
@page "/product/{id}"
<h1>Product @Id</h1>
@code {
[Parameter]
public string Id { get; set; }
}
还可以指定路由参数值的约束。 例如,若要将产品 ID 限制为: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 窗体中,通过向浏览器返回重定向响应来触发到其他页面的导航。 例如:
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 窗体中的页面布局由母版页处理。 母版页定义了一个模板,其中包含一个或多个内容占位符,供各个页面填充。 母版页在 .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
,它定义一 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>
标记都应添加到应用的主机页。