练习 - 通过创建模板重用组件

已完成

披萨公司希望“我的订单”页面向客户显示有关其过去订单的更多详细信息,例如订购过的披萨和客户下订单的时间。

模板可帮助你改进 Blazing Pizza 应用上“我的订单”页面的显示内容和功能。 在本练习中,你将创建在“我的订单”页上重复使用的分页模板组件。

创建分页模板组件

创建新的 Blazor 分页模板组件文件和分页控件。

创建文件并添加标记

  1. 在 Visual Studio Code 的 Blazor 应用项目中,创建一个名为“Components”的新文件夹,然后在名为“PaginationComponent.razor”的文件夹中创建一个新文件。

  2. 将以下 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 字段用于跟踪当前选择的项。 IncrementIndexDecrementIndexSetIndex 方法用于更改所选项索引。

方法 OnInitialized 用于将初始选定项设置为列表中的最后一项。

更新 MyOrders 组件

现在,更新“我的订单”页以使用模板组件。

  1. 在资源管理器中展开“页面”,然后选择“MyOrders.razor”。

  2. 在最后一个 @inject 指令后添加 @using 指令:

    @using BlazingPizza.Components
    

    此行使 MyOrder 组件能够使用新创建的组件模板。

  3. <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 &gt;
                            </a>
                        </div>
                    }
                </div>
                <div class="list-group-item">
                    <div class="col">
                        <OrderReview Order="@context.Order" />
                    </div>
                </div>
            </ItemContent>
        </PaginationComponent>
    }
    

代码现依赖于 PaginationComponent,它提供 OrderWithStatus 的泛型类型、按创建日期排序的过去订单列表,以及为每个项生成标签的函数。 ItemContent 呈现片段定义每个项的标记。

测试更新

  1. 在 Visual Studio Code 中,按 F5 或选择“运行”>“开始调试”。

  2. 在应用中下几个订单,然后选择“我的订单”。 验证是否看到包含订购商品的分页控件,以及是否可以选择一个订单来加载订单详细信息。

    Screenshot of the new order history page.

  3. Shift+F5 或选择“运行”>“停止调试”以停止应用。