在 ASP.NET Core 3.1 中创建视图组件
ASP.NET Core 是一个跨平台、高性能、开源的框架,用于构建现代 Web、云和基于 Internet 的应用程序。我们还可以在 Windows、macOS 和 Linux 上使用我们最喜欢的开发工具开发 Web API、移动应用程序和客户端站点单页应用程序。 Microsoft 在 ASP.NET Core 1.0 到 3.1 版本中引入了许多新功能,例如 Razor Pages、Blazor 等。在本文中,我将向您介绍 ASP.NET Core 新引入的一项功能,称为 View Components。我将解释视图组件和局部视图之间的区别。我还将解释我们如何实现可重用的视图组件,这些组件也可以被参数化以自定义以在 Web 应用程序的不同部分生成不同的响应。我们将创建一个天气小部件视图组件,它将显示我们将作为参数传递给视图组件的城市的当前天气信息。
什么是视图组件
View Component 是强大的、自包含的、可重用的 UI 组件,可以从剃刀视图一致地生成可重用的 HTML。它们可以生成静态和动态内容,可以使用参数进一步定制。 View Components 还可用于连接后端数据库或服务以获取数据。
以下是实现视图组件时要记住的要点:
- 视图组件适用于渲染块而不是整个响应。这使得它们非常适合渲染 UI 元素、小部件、动态菜单、购物车、登录页面、侧边栏等。
- 视图组件不支持视图数据或数据绑定等功能,仅依赖于在运行时作为参数提供给它们的数据
- 视图组件支持关注点分离和可测试性优势,无论在何处使用它们,它们始终生成一致的输出。
- 视图组件可以参数化自定义输出,也可以有自己的业务逻辑。
视图组件与部分视图
它们旨在完成部分视图在以前版本的 ASP.NET 等中所做的一切。当我们使用局部视图时,我们仍然依赖于控制器,我们可以访问视图数据和控制器内容,而在视图组件中我们甚至不需要控制器。视图组件有自己独立的类,可以运行一些业务逻辑并使用剃刀视图生成响应。我们可以将视图组件视为比完整 MVC 控制器开销更少的迷你控制器。
创建视图组件
视图组件由以下两部分组成
- 一个类通常派生自 Microsoft.AspNetCore.Mvc.ViewComponent 对象
- 渲染视图组件生成的响应的视图
您可以通过多种方式创建自己的视图组件类。如上所述,您可以从 ViewComponent 派生您的类
public class Navbar : ViewComponent
{
}
您可以使用 ViewComponent 属性装饰您的类
[ViewComponent]
public class Navbar
{
}
您也可以遵循命名约定,简单地创建一个后缀为 ViewComponent 的类
public class NavbarViewComponent
{
}
让我向您介绍一个简单的 ASP.NET Core 3.1 演示应用程序,我们可以在其中学习如何创建和使用我们自己的视图组件。对于本教程,我将使用 Microsoft Visual Studio 2019,但您也可以使用命令行工具创建 ASP.NET Core 3.1 Web 应用程序,例如dotnet 如果你愿意。
首先,让我们在 Visual Studio 2019 中创建一个新的 ASP.NET Core Web 应用程序项目。 对于本教程,我选择了 ViewComponentsDemoApp 作为项目名称。在 Visual Studio 中打开您的项目后,按 F5 以确保您的项目正在构建和运行且没有任何错误。如果一切正常,您应该能够在浏览器中看到以下输出。
在我们创建自定义视图组件或其关联的视图文件之前,请注意运行时会在以下路径中搜索视图:
- /Views/{Controller Name}/Components/{View Component Name}/{View Name}
- /Views/Shared/Components/{View Component Name}/{View Name}
- /Pages/Shared/Components/{View Component Name}/{View Name}
当然,就像 ASP.NET Core 中的其他所有内容一样,我们可以自定义视图搜索路径并引导运行时在其他地方查找视图,但为简单起见,我决定使用默认视图路径之一。
在 Shared 文件夹中创建一个 Components 文件夹,然后在 Components 文件夹中创建一个名为 WeatherWidget 的文件夹。这个文件夹将包含我们的自定义视图组件的类和视图文件。
在 WeatherWidget 文件夹中,创建一个名为 WeatherWidgetViewComponent 的类和一个名为 Default.cshtml 的视图。我创建名为 Default.cshtml 的视图的原因是因为在 ASP.NET Core 中,视图组件的默认视图名称是 Default。我们可以给我们的视图一个不同的名称,但我们必须指定新名称才能使用它。我建议您将视图命名为 Default.cshtml,以便运行时可以在 Views/Shared/Components/{View Component Name}/{View Name} 路径中自动找到它们,而无需任何特殊配置。
为了让事情一开始就简单,我在下面实现了一个简单的视图组件,它在调用时只传递一个参数 cityName。
public class WeatherWidgetViewComponent : ViewComponent
{
public IViewComponentResult Invoke(string cityName)
{
return View("Default", cityName);
}
}
在实现视图组件方法时,请记住以下几点
- 您可以在返回 IViewComponentResult 的同步 Invoke 方法中定义逻辑,如上例所示,也可以在返回 Task 的 InvokeAsync 方法中定义逻辑。我们将在本教程的后面部分看到此方法的示例。
- 大多数情况下,您将在 Invoke 或InvokeAsync 方法中初始化模型,并通过调用 ViewComponent View 方法将模型传递给视图。
- 在 Invoke 或 InvokeAsync 方法中,没有模型绑定并且您不处理 HTTP 请求。您应该使用传递给方法的参数,而不是 HTTP上下文中可用的任何数据。
在我们的 Default.cshtml 视图文件中,我只添加了两行。第一行表示传入的模型类型只是一个字符串,第二行将该字符串呈现在 h2 中。
@model string
<h2>@Model</h2>
调用视图组件
现在是时候从剃刀视图或布局页面调用我们的简单视图组件了。要使用视图组件,我们需要在视图内部调用 Component 类的 InvokeAsync 方法,我们也可以传递如下所示的参数。
@await Component.InvokeAsync("WeatherWidget", new { cityName = "London" })
按 F5 运行项目,您将看到页面上显示的参数值作为 h1 标题。
如果您使用的是 ASP.NET Core 1.1 及更高版本,您还可以将视图组件作为标记帮助程序调用。调用视图组件作为标签助手的语法如下
<vc:[view-component-name]
parameter1="parameter1 value"
parameter2="parameter2 value">
</vc:[view-component-name]>
所以如果我们想调用我们的 WeatherWidget 组件,我们可以使用以下代码
<vc:weather-widget city-name="London"></vc:weather-widget>
请注意,要将视图组件用作 Tag Helper,您需要使用 @addTagHelper 指令将包含视图组件的程序集注册到 _ViewImports.cshtml 文件。出于本教程的目的,我在 _ViewImports.cshtml 文件中添加了以下行
@addTagHelper *, ViewComponentsDemoApp
到目前为止,我们的视图组件还没有为我们提供任何特殊的值,因为它只渲染 h1 元素,我们甚至可以在不使用视图组件的情况下轻松渲染它。让我们在视图组件中添加一些逻辑和数据,使其更具可重用性和实用性。
对于变体,将 Invoke 方法替换为 InvokeAsync 方法并调用 GetWeatherInfo 方法,该方法根据传递给它的 cityName 参数返回伦敦、纽约和巴黎的硬编码天气信息。在现实世界的应用程序中,您可以在此处调用天气 Web 服务来获取应用程序的真实数据。
public class WeatherWidgetViewComponent: ViewComponent {
public async Task < IViewComponentResult > InvokeAsync(string cityName) {
var response = await GetWeatherInfo(cityName);
return View("Default", response);
}
private async Task < WeatherInfo > GetWeatherInfo(string cityName) {
var obj = new WeatherInfo();
obj.City = cityName;
obj.Date = DateTime.Now.ToString("dddd h:mm tt");
if (cityName == "London") {
obj.Icon = "cloudy.png";
obj.Condition = "Cloudy";
obj.Precipitation = "7%";
obj.Humidity = "70%";
obj.Wind = "6 km/h";
}
else if (cityName == "New York") {
obj.Icon = "partly_cloudy.png";
obj.Condition = "Partly Cloudy";
obj.Precipitation = "17%";
obj.Humidity = "80%";
obj.Wind = "16 km/h";
}
else if (cityName == "Paris") {
obj.Icon = "rain.png";
obj.Condition = "Rain";
obj.Precipitation = "67%";
obj.Humidity = "20%";
obj.Wind = "9 km/h";
}
return obj;
}
}
我在上面的示例中使用了以下 WeatherInfo 模型类,因此您还可以在项目根级别创建的 Models 文件夹中创建此类
namespace ViewComponentsDemoApp.Models
{
public class WeatherInfo
{
public string City { get; set; }
public string Date { get; set; }
public string Icon { get; set; }
public string Condition { get; set; }
public string Precipitation { get; set; }
public string Humidity { get; set; }
public string Wind { get; set; }
}
}
为了呈现更专业的 UI 元素而不是简单的 h1 元素,我在 Default.cshtml 视图中添加了引导卡标记,如下所示。请注意,WeatherInfo 对象现在用作模型。
<div class="card">
<div class="card-body" style="width:200px;">
<h5 class="card-title">@Model.City</h5>
<p class="card-text">
<span class="text-muted">@Model.Date</span>
</p>
<img src="@("/images/" + Model.Icon)" class="card-img-top" style="margin:auto; width: 65px;">
<h6 class="text-muted">@Model.Condition</h6>
<br />
<div>Precipitation: <span>@Model.Precipitation</span></div>
<div>Humidity: <span>@Model.Humidity</span></div>
<div>Wind: <span>@Model.Wind</span></div>
</div>
</div>
最后,我调用了 3 次 WeatherWidget 视图组件并传递了不同的城市名称作为参数。
<div class="text-center">
<h2>World Weather</h2>
<br />
<center>
<div class="container">
<div class="row">
<div class="card-group" style="margin:auto;">
<vc:weather-widget city-name="London"></vc:weather-widget>
<vc:weather-widget city-name="New York"></vc:weather-widget>
<vc:weather-widget city-name="Paris"></vc:weather-widget>
</div>
</div>
</div>
</center>
</div>
按 F5 运行示例,您将看到我们的 WeatherWidget 视图组件已经生成了作为参数传递的所有三个城市的天气信息。
总结概括
在本教程中,我谈到了 ASP.NET Core 视图组件的一项很酷的功能,以及它们如何帮助您扩展视图并为用户提供更多可重用的功能。
您的资助是我最大的动力!
金额随意,欢迎来赏!