练习 - 通过创建模板重用组件
披萨公司希望“我的订单”页面向客户显示有关其过去订单的更多详细信息,例如订购过的披萨和客户下订单的时间。
模板可帮助你改进 Blazing Pizza 应用上“我的订单”页面的显示内容和功能。 在本练习中,你将创建在“我的订单”页上重复使用的分页模板组件。
创建分页模板组件
创建新的 Blazor 分页模板组件文件和分页控件。
创建文件并添加标记
在 Visual Studio Code 的 Blazor 应用项目中,创建一个名为“Components”的新文件夹,然后在名为“PaginationComponent.razor”的文件夹中创建一个新文件。
将以下 Razor 标记添加到新创建的模板组件:
@typeparam TItem <div class="container-sm py-4"> @ItemContent(Items.ElementAt(selectedIndex)) </div> <nav aria-label="Pagination functionality"> <ul class="pagination pagination-lg justify-content-center"> <li class="page-item @(previousDisabled ? "disabled" : "")" disabled="@previousDisabled"> <a class="page-link" @onclick="@(() => SetIndex(0))"> <span>⏪</span> </a> </li> <li class="page-item @(previousDisabled ? "disabled" : "")" disabled="@previousDisabled"> <a class="page-link" @onclick="DecrementIndex"><span>⬅️</span></a> </li> @foreach ((int index, TItem item) in Items.Select((item, index) => (index, item))) { var isActive = index == selectedIndex; <li class="page-item @(isActive ? "active" :"")"> <a class="page-link" @onclick="@(() => SetIndex(index))"> @ItemLabel(item) </a> </li> } <li class="page-item @(nextDisabled ? "disabled" : "")" disabled="@nextDisabled"> <a class="page-link" @onclick="IncrementIndex"><span>➡️</span></a> </li> <li class="page-item @(nextDisabled ? "disabled" : "")" disabled="@nextDisabled"> <a class="page-link" @onclick="@(() => SetIndex(Items.Count - 1))"> <span>⏩</span> </a> </li> </ul> </nav>
标记接受泛型类型参数 TItem
,定义用于显示所选项的容器,并使用 <nav>
元素显示分页控件。
此类控件使用 <ul>
元素,每个列表项都是一个页码。 页码由 ItemLabel
呈现片段定义,呈现片段作为参数传入。 ItemLabel
呈现片段在使用模板的组件中定义。
添加代码指令
添加 @code
指令以处理处于活动状态的项。
@code {
[Parameter, EditorRequired]
public required List<TItem> Items { get; set; }
[Parameter, EditorRequired]
public required RenderFragment<TItem> ItemContent { get; set; }
[Parameter, EditorRequired]
public required Func<TItem, MarkupString> ItemLabel { get; set; }
int selectedIndex;
bool previousDisabled => selectedIndex == 0;
bool nextDisabled => selectedIndex == Items.Count - 1;
void IncrementIndex() => selectedIndex++;
void DecrementIndex() => selectedIndex--;
void SetIndex(int index) => selectedIndex = index;
protected override void OnInitialized() =>
selectedIndex = Items.Count - 1;
}
前文所述的代码块定义使用模板所需的参数。
Items
参数是要显示的TItem
项列表。ItemContent
参数是一个呈现片段,用于定义如何显示所选项的内容。ItemLabel
参数是一个函数,用于定义如何显示每个项的标签。
selectedIndex
字段用于跟踪当前选择的项。 IncrementIndex
、DecrementIndex
和 SetIndex
方法用于更改所选项索引。
方法 OnInitialized
用于将初始选定项设置为列表中的最后一项。
更新 MyOrders 组件
现在,更新“我的订单”页以使用模板组件。
在资源管理器中展开“页面”,然后选择“MyOrders.razor”。
在最后一个
@inject
指令后添加@using
指令:@using BlazingPizza.Components
此行使
MyOrder
组件能够使用新创建的组件模板。在
<div class="main">
标记中,将if
/else if
/else
逻辑块中现有的else
分支替换为以下代码:else { <PaginationComponent TItem="OrderWithStatus" Items="ordersWithStatus.OrderBy(o => o.Order.CreatedTime).ToList()" ItemLabel='item => new($"{item.Order.CreatedTime:ddd, MMM. d, yyyy}")'> <ItemContent> <div class="list-group-item bg-secondary text-white"> <div class="col"> <h5>@($"{context.Order.CreatedTime:dddd, MMMM d, yyyy hh:mm tt}")</h5> Items: <strong>@context.Order.Pizzas.Count</strong> </div> <div class="col"> Status: <strong>@context.StatusText</strong> </div> @if (@context.StatusText != "Delivered") { <div class="col flex-grow-0"> <a href="myorders/@context.Order.OrderId" class="btn btn-success"> Track > </a> </div> } </div> <div class="list-group-item"> <div class="col"> <OrderReview Order="@context.Order" /> </div> </div> </ItemContent> </PaginationComponent> }
代码现依赖于 PaginationComponent
,它提供 OrderWithStatus
的泛型类型、按创建日期排序的过去订单列表,以及为每个项生成标签的函数。 ItemContent
呈现片段定义每个项的标记。