作者:Daniel Roth 和 Luke Latham
重要
Blazor WebAssembly 为预览版状态
ASP.NET Core 3.0 支持 Blazor Server 。 Blazor WebAssembly 在 ASP.NET Core 3.1 中为预览版。
本教程演示如何生成和修改 Blazor 应用。
按照 ASP.NET Core Blazor 入门 文章中的指南创建用于本教程的 Blazor 项目。 将项目命名为 ToDoList 。
在 Pages 文件夹中浏览应用的三个页面:主页、计数器和提取数据。 这些页面由 Razor 组件文件(Index.razor 、Counter.razor 和 FetchData.razor )实现。
在“计数器”页上,选择“单击我” 按钮,在不刷新页面的情况下增加计数器值。 增加网页的计数器值通常需要编写 JavaScript。 通过 Blazor,可以改为编写 C#。
检查 Counter.razor 文件中 Counter
组件的实现。
Pages/Counter.razor:
@page "/counter" <h1>Counter</h1> <p>Current count: @currentCount</p> <button class="btn btn-primary" @onclick="IncrementCount">Click me</button> @code { private int currentCount = 0; private void IncrementCount() { currentCount++; } }
使用 HTML 定义 Counter
组件的 UI。 动态呈现逻辑(例如,循环、条件、表达式)是使用名为 Razor 的嵌入式 C# 语法添加的。 HTML 标记和 C# 呈现逻辑在构建时转换为组件类。 生成的 .NET 类的名称与文件名匹配。
组件类的成员在 @code
块中定义。 在 @code
块中,可以指定组件状态(属性、字段)和方法用于处理事件或定义其他组件逻辑。 然后,可以将这些成员用作组件呈现逻辑的一部分,并用于处理事件。
选中“单击我” 按钮时:
Counter
组件的已注册 onclick
处理程序(IncrementCount
方法)。Counter
组件重新生成其呈现树。修改 Counter
组件的 C# 逻辑,使计数递增 2 而不是 1。
@page "/counter" <h1>Counter</h1> <p>Current count: @currentCount</p> <button class="btn btn-primary" @onclick="IncrementCount">Click me</button> @code { private int currentCount = 0; private void IncrementCount() { currentCount += 2; } }
重新生成并运行应用以查看更改。 选择“单击我” 按钮。 计数器的值将增加 2。
使用 HTML 语法将组件加入到另一个组件中。
通过向 Index
组件 (Index.razor ) 添加 <Counter />
元素,将 Counter
组件添加到应用的 Index
组件。
如果在此体验中使用的是 Blazor WebAssembly,则 Index
组件使用 SurveyPrompt
组件。 将 <SurveyPrompt>
元素替换为 <Counter />
元素。 如果在此体验中使用的是 Blazor Server 应用,请向 Index
组件添加 <Counter />
元素:
Pages/Index.razor:
@page "/" <h1>Hello, world!</h1> Welcome to your new app. <Counter />
重新生成并运行应用。 Index
组件有其自己的计数器。
组件也可以有参数。 组件参数由具有 [Parameter]
的组件类上的公共属性定义。 使用这些属性在标记中为组件指定参数。
更新组件的 @code
C# 代码,如下所示:
[Parameter]
特性添加公共 IncrementAmount
属性。currentCount
的值时,更改 IncrementCount
方法以使用 IncrementAmount
属性。Pages/Counter.razor:
@page "/counter" <h1>Counter</h1> <p>Current count: @currentCount</p> <button class="btn btn-primary" @onclick="IncrementCount">Click me</button> @code { private int currentCount = 0; [Parameter] public int IncrementAmount { get; set; } = 1; private void IncrementCount() { currentCount += IncrementAmount; } }
使用属性在 Index
组件的 <Counter>
元素中指定 IncrementAmount
参数。 将计数器递增值设置为 10。
Pages/Index.razor:
@page "/" <h1>Hello, world!</h1> Welcome to your new app. <Counter IncrementAmount="10" />
重新加载 Index
组件。 每次选择“单击我” 按钮时,计数器值递增 10。 Counter
组件中的计数器继续递增 1。
Counter.razor 文件顶部的 @page
指令指定 Counter
组件是路由终结点。 Counter
组件处理发送到 /counter
的请求。 如果没有 @page
指令,组件将无法处理路由的请求,但该组件仍可以被其他组件使用。
如果使用的是 Blazor Server 应用,则 WeatherForecastService
服务在 Startup.ConfigureServices
中注册为单一实例。 可通过依赖关系注入 (DI) 在整个应用中使用服务的实例:
public void ConfigureServices(IServiceCollection services) { services.AddRazorPages(); services.AddServerSideBlazor(); services.AddSingleton<WeatherForecastService>(); }
@inject
指令用于将 WeatherForecastService
服务的实例注入到 FetchData
组件中。
Pages/FetchData.razor:
@page "/fetchdata" @using ToDoList.Data @inject WeatherForecastService ForecastService
FetchData
组件使用注入的服务(作为 ForecastService
)来检索 WeatherForecast
对象的数组:
@code { private WeatherForecast[] forecasts; protected override async Task OnInitializedAsync() { forecasts = await ForecastService.GetForecastAsync(DateTime.Now); } }
如果使用的是 Blazor WebAssembly 应用,则注入了 HttpClient
,以从 wwwroot/sample-data 文件夹的 weather.json 文件中获取天气预测数据。
Pages/FetchData.razor:
@inject HttpClient Http ... protected override async Task OnInitializedAsync() { forecasts = await Http.GetJsonAsync<WeatherForecast[]>("sample-data/weather.json"); }
@foreach
循环用于将每个预测实例呈现为“天气”数据表中的一行:
<table class="table"> <thead> <tr> <th>Date</th> <th>Temp. (C)</th> <th>Temp. (F)</th> <th>Summary</th> </tr> </thead> <tbody> @foreach (var forecast in forecasts) { <tr> <td>@forecast.Date.ToShortDateString()</td> <td>@forecast.TemperatureC</td> <td>@forecast.TemperatureF</td> <td>@forecast.Summary</td> </tr> } </tbody> </table>
向应用添加一个实现简单待办事项列表的新组件。
向 Pages 文件夹中的应用添加一个名为 Todo.razor 的空文件:
为组件提供初始标记:
@page "/todo" <h1>Todo</h1>
将 Todo
组件添加到导航栏。
NavMenu
组件 (Shared/NavMenu.razor ) 用于应用的布局。 布局是可以避免应用中出现重复内容的组件。
通过在“Shared/NavMenu.razor” 文件中的现有列表项下添加以下列表项标记,为 Todo
组件添加一个 <NavLink>
元素:
<li class="nav-item px-3"> <NavLink class="nav-link" href="todo"> <span class="oi oi-list-rich" aria-hidden="true"></span> Todo </NavLink> </li>
重新生成并运行应用。 访问新的“待办事项”页面,确认指向 Todo
组件的链接有效。
向项目的根目录添加“TodoItem.cs” 文件,以保存一个用于表示待办项的类。 为 TodoItem
类使用以下 C# 代码:
public class TodoItem { public string Title { get; set; } public bool IsDone { get; set; } }
返回到 Todo
组件 (Pages/Todo.razor ):
@code
块中为待办项添加一个字段。 Todo
组件使用此字段来维护待办项列表的状态。foreach
循环,以将每个待办项呈现为列表项 (<li>
)。@page "/todo" <h1>Todo</h1> <ul> @foreach (var todo in todos) { <li>@todo.Title</li> } </ul> @code { private IList<TodoItem> todos = new List<TodoItem>(); }
该应用需要 UI 元素来将待办项添加到列表。 在未排序列表 (<ul>...</ul>
) 下方添加一个文本输入 (<input>
) 和一个按钮 (<button>
):
@page "/todo" <h1>Todo</h1> <ul> @foreach (var todo in todos) { <li>@todo.Title</li> } </ul> <input placeholder="Something todo" /> <button>Add todo</button> @code { private IList<TodoItem> todos = new List<TodoItem>(); }
重新生成并运行应用。 选择“添加待办项” 按钮时没有任何反应,因为没有事件处理程序连接到该按钮。
向 Todo
组件添加 AddTodo
方法,并使用 @onclick
属性注册该方法以选择按钮。 选择按钮时,会调用 AddTodo
C# 方法:
<input placeholder="Something todo" /> <button @onclick="AddTodo">Add todo</button> @code { private IList<TodoItem> todos = new List<TodoItem>(); private void AddTodo() { // Todo: Add the todo } }
要获得新待办项标题,请在 @code
块顶部添加 newTodo
字符串字段,并使用 <input>
元素中的 bind
属性将其绑定到文本输入的值:
private IList<TodoItem> todos = new List<TodoItem>(); private string newTodo;
<input placeholder="Something todo" @bind="newTodo" />
更新 AddTodo
方法,将具有指定标题的 TodoItem
添加到列表。 通过将 newTodo
设置为空字符串来清除文本输入的值:
@page "/todo" <h1>Todo</h1> <ul> @foreach (var todo in todos) { <li>@todo.Title</li> } </ul> <input placeholder="Something todo" @bind="newTodo" /> <button @onclick="AddTodo">Add todo</button> @code { private IList<TodoItem> todos = new List<TodoItem>(); private string newTodo; private void AddTodo() { if (!string.IsNullOrWhiteSpace(newTodo)) { todos.Add(new TodoItem { Title = newTodo }); newTodo = string.Empty; } } }
重新生成并运行应用。 在待办项列表中添加一些待办项以测试新代码。
每个待办项的标题文本都可以编辑,复选框可以帮助用户跟踪已完成的项。 为每个待办项添加一个复选框输入,并将它的值绑定到 IsDone
属性。 将 @todo.Title
更改为绑定到 @todo.Title
的 <input>
元素:
<ul> @foreach (var todo in todos) { <li> <input type="checkbox" @bind="todo.IsDone" /> <input @bind="todo.Title" /> </li> } </ul>
若要验证这些值是否已绑定,请更新 <h1>
标头以显示尚未完成的待办项计数(IsDone
是 false
)。
<h1>Todo (@todos.Count(todo => !todo.IsDone))</h1>
完成的 Todo
组件 (Pages/Todo.razor ):
@page "/todo" <h1>Todo (@todos.Count(todo => !todo.IsDone))</h1> <ul> @foreach (var todo in todos) { <li> <input type="checkbox" @bind="todo.IsDone" /> <input @bind="todo.Title" /> </li> } </ul> <input placeholder="Something todo" @bind="newTodo" /> <button @onclick="AddTodo">Add todo</button> @code { private IList<TodoItem> todos = new List<TodoItem>(); private string newTodo; private void AddTodo() { if (!string.IsNullOrWhiteSpace(newTodo)) { todos.Add(new TodoItem { Title = newTodo }); newTodo = string.Empty; } } }
重新生成并运行应用。 添加待办项以测试新代码。