重庆网站自己推广,网站制作费用大概多少,东莞市建设企业网站企业,固安县城乡和住房建设局网站翻译自 Waqas Anwar 2021年4月15日的文章 《A Developer’s Guide To Blazor Templated Components》 [1]在我之前的一篇文章 Blazor 组件入门指南中#xff0c;我介绍了组件参数#xff0c;并向您展示了如何将数据作为参数传递给 Blazor 组件以定制化其功能。在这篇文章中我介绍了组件参数并向您展示了如何将数据作为参数传递给 Blazor 组件以定制化其功能。在这篇文章中我将更进一步向您展示如何将一个或多个 UI 模板作为参数传递给一个称之为模板化组件的不同类型的 Blazor 组件。下载源码[2]Blazor 模板化组件概述Blazor 模板化组件是一种接受将一个或多个 UI 模板作为参数的组件。这有助于组件的可重用性因为您只需要创建一次模板化组件然后使用该组件的每个页面都可以提供其 UI 模板模板化组件可以根据页面需求渲染此 UI 模板。本文中的模板化组件示例包括一个允许用户指定表格表头、行和页脚模板的表格组件。一个允许用户呈现具有相同外观和体验而具有不同内容的小部件组件。一个允许用户指定一个模板来呈现项目符号或编号等列表项的列表组件。一个允许用户以列表、网格或卡片视图来显示数据的列表组件。当我们创建 Blazor 组件的一个参数时我们通常将其类型指定为 string、int 或者其他内置 .NET 数据类型。为了创建一个模板化组件我们需要创建类型为 RenderFragment 或 RenderFragmentT 的组件参数。RenderFragment 允许我们提供一个可以由模板化组件渲染的 UI 内容片段作为一个委托实现将其内容写入到 RenderTreeBuilder。[Parameter]
public RenderFragment HeaderTemplate { get; set; }
RenderFragmentT 更进一步允许我们传入参数的类型 T可以用它来自定义模板化组件的输出。[Parameter]
public RenderFragmentT RowTemplate { get; set; }
从一个实例开始为了详细了解模板化组件我决定构建一个 TableWidget 模板化组件它允许我们自定义不同格式的表头、行和页脚。在创建第一个模板化组件之前我们先来创建一个新的 Blazor Server 应用程序并添加其基本功能以表格格式呈现一些数据。在 Blazor Server 应用程序中创建一个 Data 文件夹并在 Data 文件夹中添加以下两个模型类。Product.cspublic class Product
{public int Id { get; set; }public string Title { get; set; }public decimal Price { get; set; }public int Quantity { get; set; }
}
Order.cspublic class Order
{public int Id { get; set; }public string OrderNo { get; set; }public DateTime OrderDate { get; set; }public string Status { get; set; }public decimal OrderTotal { get; set; }
}
在项目中创建一个 Services 文件夹并在 Services 文件夹中添加如下的 IProductService 和 ProductService。在本教程中我仅返回一些用于生成表格的模拟数据。IProductService.cspublic interface IProductService
{ListProduct GetTopSellingProducts();
}
ProductService.cspublic class ProductService : IProductService
{public ListProduct GetTopSellingProducts(){return new ListProduct(){new Product(){Id 1,Title Wireless Mouse,Price 29.99m,Quantity 3},new Product(){Id 2,Title HP Headphone,Price 79.99m,Quantity 4},new Product(){Id 3,Title Sony Keyboard,Price 119.99m,Quantity 5}};}
}
接下来在同一 Services 文件夹中创建 IOrderService 和 OrderService 并添加一些用于生成表格的模拟订单数据。IOrderService.cspublic interface IOrderService
{ListOrder GetLatestOrders();
}
OrderService.cspublic class OrderService : IOrderService
{public ListOrder GetLatestOrders(){return new ListOrder(){new Order(){Id 1, OrderNo 12345,OrderDate DateTime.Today.AddDays(-2),Status Pending,OrderTotal 399.99m},new Order(){Id 2,OrderNo 67890,OrderDate DateTime.Today.AddDays(-5),Status Completed,OrderTotal 199.99m},new Order(){Id 3,OrderNo 13579,OrderDate DateTime.Today.AddDays(-7),Status Completed,OrderTotal 249.99m}};}
}
我们需要使用依赖注入将上述服务注入到 Blazor 组件中为此我们需要在 Startup.cs 文件中注册上述服务。如果您想了解关于依赖注入的更多知识可以阅读我的文章 A Step by Step Guide to ASP.NET Core Dependency Injection[3]。Startup.cspublic void ConfigureServices(IServiceCollection services)
{services.AddRazorPages();services.AddServerSideBlazor();services.AddSingletonWeatherForecastService();services.AddScopedIOrderService, OrderService();services.AddScopedIProductService, ProductService();
}
接下来在项目 Pages 文件夹中创建 Blazor 组件 Dashboard.razor 及其对应的代码隐藏文件 Dashboard.razor.cs。如果您不熟悉 Blazor 组件及代码隐藏文件请阅读我的文章 Blazor 组件入门指南。组件的代码隐藏文件 Dashboard.razor.cs 中同时注入了 IOrderService 和 IProductService然后我们将使用 GetLatestOrders 和 GetTopSellingProducts 方法来填充我们的本地 Orders 和 Products 列表。Dashboard.razor.cspublic partial class Dashboard
{[Inject]private IOrderService OrderService { get; set; }[Inject]private IProductService ProductService { get; set; }private ListOrder Orders { get; set; }private ListProduct Products { get; set; }protected override void OnInitialized(){Orders OrderService.GetLatestOrders();Products ProductService.GetTopSellingProducts();}
}
Razor 组件视图文件将简单地在 Orders 和 Products 上运行 foreach 循环并生成 HTML 表格。page /dashboard
h1Dashboard/h1
br /
div classrowdiv classcolif (Orders ! null){table classtable table-striped table-borderedthead classthead-darktrth scopecolOrder/thth scopecolDate/thth scopecolStatus/thth scopecolTotal/th/tr/theadtbodyforeach (var order in Orders){trtdorder.OrderNo/tdtdorder.OrderDate.ToShortDateString()/tdtdorder.Status/tdtdorder.OrderTotal/td/tr}/tbody/table}/divdiv classcolif (Products ! null){h3Top Selling Products/h3table classtable table-striped table-borderedthead classthead-darktrth scopecolTitle/thth scopecolPrice/thth scopecolQuantity/th/tr/theadtbodyforeach (var product in Products){trtdproduct.Title/tdtdproduct.Price/tdtdproduct.Quantity/td/tr}/tbody/table}/div
/div
此时如果您运行项目将在页面上看到以下两个表格。截至目前我们尚没有创建任何模板化组件但您会感觉到我们很快将需要一个因为上面显示的订单和产品表格几乎都具有相同的外观和体验并且我们在上面的 foreach 循环中复制了大量的 HTML 来生成这两张表格。一个好注意是创建一个模板化组件然后重用该组件来生成上述两张表格并且仍然能够自定义它们显示的表头和数据行。让我们来创建我们的第一个模板化组件命名为 TableWidget 组件。创建 Blazor 模板化组件在 Shared 文件夹中新建一个 Razor 组件 TableWidget.razor并在其中添加以下代码TableWidget.razortypeparam TItem
br /
h3Title/h3
table classtable table-striped table-borderedthead classthead-darktrHeaderTemplate/tr/theadtbodyforeach (var item in Items){trRowTemplate(item)/tr}/tbodytfoottrFooterTemplate/tr/tfoot
/table
code {[Parameter]public string Title { get; set; }[Parameter]public RenderFragment HeaderTemplate { get; set; }[Parameter]public RenderFragmentTItem RowTemplate { get; set; }[Parameter]public RenderFragment FooterTemplate { get; set; }[Parameter]public IReadOnlyListTItem Items { get; set; }
}
我们的 TableWidget 组件包含以下三个模板[Parameter]
public RenderFragment HeaderTemplate { get; set; }[Parameter]
public RenderFragmentTItem RowTemplate { get; set; }[Parameter]
public RenderFragment FooterTemplate { get; set; }
HeaderTemplate 允许用户在表格的表头中呈现任意 UI 模板。此模板用于在 thead 元素内渲染表格表头的单元格。thead classthead-darktrHeaderTemplate/tr
/thead
FooterTemplate 与 HeaderTemplate 类似它允许用户在表格的页脚中呈现任意 UI 模板。此模板用于在 tfoot 元素内渲染表格页脚的单元格。tfoottrFooterTemplate/tr
/tfoot
RowTemplate 的类型为 RanderFragmentTItem它允许用户使用任意的 .NET 类型渲染 UI 模板。该类型不是固定的而是使用组件顶部的 typeparam 指令声明为一个泛型类型。typeparam TItem
我们还在组件中创建了一个 TItem 对象的集合以便我们可以迭代该集合生成表格的行。[Parameter]
public IReadOnlyListTItem Items { get; set; }
我们将要传入 UI 模板中的 TItem 类型的对象会使用以下 foreach 循环进行渲染。您很快就会看到这将如何帮助我们使用相同的 TableWidget 组件同时渲染产品和订单表格。tbodyforeach (var item in Items){trRowTemplate(item)/tr}
/tbody
使用 Blazor 模板化组件的不同方式现在是时候来实践一下我们的 TableWidget 组件了我们可以通过不同的方式使用这个组件。用下面的 TableWidget 组件替换我们前面生成的 Recent Orders 表格。div classcolif (Orders ! null){TableWidget TitleRecent Orders ItemsOrdersHeaderTemplateth scopecolOrder/thth scopecolDate/thth scopecolStatus/thth scopecolTotal/th/HeaderTemplateRowTemplatetdcontext.OrderNo/tdtdcontext.OrderDate.ToShortDateString()/tdtdcontext.Status/tdtdcontext.OrderTotal/td/RowTemplate/TableWidget}
/div
在上面的代码片段中Items 属性是使用我们的从服务获取的 Orders 列表进行初始化的。然后我们选择使用 HeaderTemplate 和 RowTemplate 来生成表格的表头和数据行。您可能在想 context 是从哪里来的context 是一个隐式参数所有类型为 RenderFragmentT 的组件参数都可以使用。我们可以使用 context 访问我们正在处理对象的属性。在上面的示例中context 将向模板提供订单信息。如果此时您运行项目会在页面上看到以下两个表格。现在最近的订单Recent Orders表格是使用我们的 TableWidget 组件生成的了。让我们重用 TableWidget 组件来生成热卖产品Top Selling Products表格。这一次我们传递了 Products 列表给它还指定了我们自己的 Contextproduct这意味着现在我们可以使用 product 取代隐式参数 context 来访问产品的属性。div classcolif (Products ! null){TableWidget TitleTop Selling Products ItemsProducts ContextproductHeaderTemplateth scopecolTitle/thth scopecolPrice/thth scopecolQuantity/th/HeaderTemplateRowTemplatetdproduct.Title/tdtdproduct.Price/tdtdproduct.Quantity/td/RowTemplate/TableWidget}
/div
您还可以在模板级别指定上下文Context如下面的示例所示其中将 Contextproduct 添加到了 RowTemplate。TableWidget TitleTop Selling Products ItemsProductsHeaderTemplateth scopecolTitle/thth scopecolPrice/thth scopecolQuantity/th/HeaderTemplateRowTemplate Contextproducttdproduct.Title/tdtdproduct.Price/tdtdproduct.Quantity/td/RowTemplate
/TableWidget
现在如果您运行该项目您将看到页面上显示了以下两个表格但是我们知道这次这两个表格是使用我们的模板化组件 TableWidget 渲染的。该示例清楚地演示了同一个模板化组件可用于生成不同类型的 UI并且可以根据我们的应用程序需求渲染不同类型的对象。下面让我们通过另外两个例子重用一下我们的 TableWidget 组件它们将显示同样的最近订单Recent Orders和热销产品Top Selling Products但布局略有改变。div classrowdiv classcolif (Orders ! null){TableWidget TitleRecent Orders ItemsOrdersHeaderTemplateth scopecol colspan2Order Details/thth scopecolStatus/thth scopecolTotal/th/HeaderTemplateRowTemplate Contextordertd colspan2bOrder No: /border.OrderNobr /bOrder Date: /border.OrderDate.ToShortDateString()/tdtdorder.Status/tdtdorder.OrderTotal/td/RowTemplate/TableWidget}/divdiv classcolif (Products ! null){TableWidget TitleTop Selling Products ItemsProducts TItem”Product”RowTemplate Contextproducttdh2product.Title/h2h4bproduct.Price.ToString(C)/b/h4/td/RowTemplateFooterTemplatetd classtext-rightbLast 30 Days/b/td/FooterTemplate/TableWidget}/div
/div
在使用泛型类型组件时会尽可能推断类型参数。不过我们可以选择使用一个特性来显式指定类型该特性的名称与类型参数相同在上面的示例中是 TItem。此时如果您运行该项目您将在页面上看到使用同一个 TableWidget 模板化组件渲染的全部四个表格。创建通用模板化组件我们的 TableWidget 组件很好我们已见识了重用它的多个示例但该组件的问题是它只生成了 HTML 表格。如果我们想要创建一个更通用的组件可以重用它来生成任何类型的 UI比如表格、卡片、项目符号等。我们可以通过从模板化组件中删除所有的标签来轻松地创建这样一个组件。让我们来创建一个通用的 ListWidget 组件来实战练习一下这种组件。在 Shared 文件夹中创建一个新的 ListWidget.razor 组件并在其中添加以下代码。这次在组件中没有 HTML 标签在 foreach 循环中仅有一个 ItemTemplate。这意味着我们可以使用这个 ListWidget 组件自由地生成任意类型的列表。ListWidget.razortypeparam TItemforeach (var item in Items)
{ItemTemplate(item)
}code {[Parameter]public RenderFragmentTItem ItemTemplate { get; set; }[Parameter]public IReadOnlyListTItem Items { get; set; }
}
假如我们想要使用这个 ListWidget 组件生成 bootstrap 列表那么我们可以使用下面的代码段来实现这一操作。ul classlist-groupli classlist-group-item d-flex justify-content-between align-items-center activeLatest Products/liListWidget ItemsProducts ContextproductItemTemplateli classlist-group-item d-flex justify-content-between align-items-centerproduct.Titlebproduct.Price.ToString(C)/bspan classbadge badge-primary badge-pillproduct.Quantity/span/li/ItemTemplate/ListWidget
/ul
运行该项目您将看到以 bootstrap 列表方式生成的相同产品的列表。现在假设您有另一个页面其中需要使用 div 和 a 标签以不同形式展示产品列表那么您可以再次重用相同的 ListWidget 组件这次生成如下标记div classlist-groupa classlist-group-item d-flex justify-content-between align-items-center activeLatest Products/aListWidget ItemsProducts Contextproduct TItemProductItemTemplatea href# classlist-group-item list-group-item-action flex-column align-items-startdiv classd-flex w-100 justify-content-betweenh5 classmb-1bproduct.Title/b/h5small classtext-mutedproduct.Quantity units left/small/divp classmb-1product.Price.ToString(C)/p/a/ItemTemplate/ListWidget
/div
运行该项目您将看到类似以下内容的输出。总结在本教程中我概述了 Blazor 模板化组件并创建了两种类型的模板化组件。然后我们实践了几个重用 TableWidget 和 ListWidget 组件来生成不同类型标记的例子。我不得不承认模板化组件是 Blazor 开发者工具箱中的一个很好的补充我们可以使用这些组件创建一些令人惊叹的可重用组件。相关阅读Blazor Server 和 WebAssembly 应用程序入门指南Blazor 组件入门指南Blazor 数据绑定开发指南Blazor 事件处理开发指南Blazor 组件之间使用 EventCallback 进行通信Blazor 路由及导航开发指南Blazor 模板化组件开发指南(本文)相关链接https://www.ezzylearning.net/tutorial/a-developers-guide-to-blazor-templated-components A Developer’s Guide To Blazor Templated Components ↩︎https://github.com/ezzylearning/BlazorTemplatedComponentDemo 下载源码 ↩︎https://www.ezzylearning.net/tutorial/a-step-by-step-guide-to-asp-net-core-dependency-injection A Step by Step Guide to ASP.NET Core Dependency Injection ↩︎作者 Waqas Anwar译者 技术译民出品 技术译站https://ITTranslator.cn/