10 个您可能不知道的 Blazor 功能
这里有您希望 Blazor 能够做到的十大功能——它实际上也能做到!
引言
Blazor 仍然是一项相对较新的技术,但自 2018 年发布以来,它已经获得了惊人的发展势头。Blazor 最初是一个实验性项目,现在已作为 .NET 5 的一部分发布,并被认为是生产就绪的。
它对 .NET 开发人员的主要吸引力在于,他们可以使用自己喜欢的语言(如 C#)编写单页应用程序,并重用现有的 .NET 库和框架。与大多数现代 Web 技术一样,Blazor 也在快速发展。每隔几个月,其开发人员就会发布包含新功能预览版。
如果您在早期尝试过 Blazor,可能会遇到现在已不存在的障碍和限制。Blazor 与 ASP.NET Core 紧密集成,支持所有不受浏览器安全沙箱限制的主要 .NET API,并提供与 JavaScript 的双向集成。这些功能使其成为构建企业 Web 应用程序的强大选择。
如果您仍然对使用 Blazor 有疑虑,请继续阅读。以下是您希望 Blazor 能够做到的——但它实际上已经做到的十大功能!
.NET 5 和 C# 9
Blazor 作为 .NET 的一部分发布,并支持所有相关 API。有些 API(如文件 I/O)由于限制访问本地文件系统,在浏览器上下文中没有意义。
Blazor 还支持最新的 C# 语言版本 9.0。使用最新的语言构造不仅可以提高代码的简洁性和可读性,还可以实际提高性能!以下是您可以在 Blazor 应用中使用的一些有用的 C# 9.0 功能的快速概述。
您知道可以使用简化的对象初始化来节省击键次数吗?创建新实例时不再需要重新声明类。这种冗余的代码
Person person = new Person();
简化为:
Person person = new ();
使用新的 switch 表达式来简化逻辑。原本像这样:
public int DoMath(int a, int b, Operator op)
{
switch(op)
{
case Operator.Add:
return a + b;
case Operator.Sub:
return a - b;
case Operator.Mult:
return a * b;
default:
return a / b;
}
}
现在可以更简洁地表达:
public int DoBetterMath(int a, int b, Operator op) =>
op switch
{
Operator.Add => a + b,
Operator.Sub => a - b,
Operator.Mult => a * b,
_ => a / b
};
别忘了,您还可以使用快速的 SpanT
进行数组和 string
操作,以及新的 范围运算符。
Markdown
Markdown 作为 HTML 的流行且轻量级的替代品,创建基于 Web 的文档。其简单的语法使编写起来非常容易,无需担心嵌套标签或特殊控件。
GitHub 等存储库、大多数博客引擎和内容管理系统 (CMS) 都支持 Markdown。浏览器缺乏原生的 Markdown 支持,只能在其渲染为 HTML 后显示。各种开源库可以格式化、解析、验证和转换 markdown。
由于 Blazor 支持现有的 .NET 库,因此在 Blazor 中构建 Markdown 编辑器非常容易。下图演示了一个简单的 Blazor WebAssembly
Markdown 编辑器,只需几分钟即可创建。
要亲眼看看,请创建一个新的 Blazor WebAssembly
项目。如果您不确定如何操作,请查看 此学习模块。接下来,添加对 Markdig 包的引用。更新 Index 页以包含此行:
<div class="row"> <div class="col-6"> <textarea @bind-value="@MarkdownText" @bind-value:event="oninput" rows="20" cols="80"> </textarea> </div> <div class="col-6"> <textarea @bind-value="@Html" @bind-value:event="oninput" rows="20" cols="80"> </textarea> </div> </div>
在 后台代码 中,像这样实现属性:
private string markdown;
public string MarkdownText
{
get => markdown;
set
{
if (value != markdown)
{
markdown = value;
OnMarkdownChanged();
}
}
}
public string Html { get; set; }
然后转换就这么简单:
private void OnMarkdownChanged() => Html = Markdown.ToHtml(markdown);
现在您拥有了一个实时 Markdown 编辑器,可以在您输入时刷新 HTML。
gRPC
流行的 gRPC 框架在端点之间提供高性能通信。它使用较新的 HTTP/2 协议,该协议允许在单个连接上并行请求。有效载荷是压缩的二进制格式,因此其网络占用空间通常比传统的 REST 或甚至 WCF SOAP 实现小得多。
根据这份 gRPC 架构文档,gRPC 的速度最高可达 JSON 序列化的八倍,并且有效载荷比等效的 REST 服务小 60% 到 80%。gRPC 内置于 .NET Core 中,并且 .NET Core 随附的默认轻量级 Web 服务器 (Kestrel) 支持 HTTP/2。
浏览器限制使得无法实现标准的 gRPC 浏览器客户端,因为不存在控制 HTTP/2 通信的 API。一个名为 gRPC-Web 的开源项目提供了一个在浏览器中工作的扩展,并包含一个代理来处理这两种实现的请求,从而可以在 Blazor WebAssembly
应用程序中使用 gRPC。
安装和配置所需的包后,gRPC 调用看起来几乎与 RESTful 请求相同。以下是一个示例调用:
forecasts =
await WeatherForecastsClient.GetWeatherAsync(new WeatherForecast()).Forecasts;
gRPC 要求所有 API 都具有自定义输入和自定义输出。在上面的示例中,自定义输入 WeatherForecast
表示对天气预报的请求,响应包含 Forecasts
属性有效载荷。
您可以在博文 如何在 App Service 上将 gRPC-Web 与 Blazor WebAssembly 结合使用 中看到完整的端到端示例。还有一个开源项目可以从一组接口生成所有必需的 gRPC 基础结构。请查看 gRPC generator,了解“grWizard
”的实际应用。
GraphQL
GraphQL 是另一个流行的协议,它正在迅速取代现代 Web 应用程序中的传统 REST。Facebook 创建它是为了提高其用户界面性能,并专门设计用于简化前端客户端的通信。他们并不打算将其用于像 gRPC 这样的进程间通信。
GraphQL 因其强类型架构、易于发现以及单个请求聚合多个后端响应的能力而广受欢迎。其最受欢迎的功能是使客户端能够定义响应形状,只接收特定需要的数据,避免过度获取。
考虑一个包含联系人信息的 T数据集。要实现一个仅返回姓名的自动完成搜索框,您可以发出如下请求:
{
contact(filter: 'likness') {
lastname,
firstname
}
}
请求仅返回姓名。在不同的组件中,您可能想显示更多数据并按如下方式设置请求形状:
{
contact(filter: 'likness') {
lastname,
phone,
address {
street,
zipCode
}
}
}
流行的 .NET GraphQL 库包括 GraphQL.NET 和 Hot Chocolate。要将 GraphQL 与 Blazor WebAssembly
应用结合使用,请遵循 Strawberry Shake 入门指南。Strawberry Shake 是 HotChocolate(服务器端 GraphQL)的配套工具,它创建 .NET GraphQL 客户端代理,以使用强类型有效载荷来消耗端点。
EF Core 和 Azure Cosmos DB
Entity Framework Core (EF Core) 是一个对象到数据库的映射器,它使开发人员能够使用域对象和一致、强类型的DataAccess API 来管理数据持久性。它支持各种数据库,包括 SQL Server、MySQL、PostgreSQL、SQLite 和 Azure Cosmos DB。EF Core 是跨平台的,并且针对 .NET 5,因此与 Blazor 项目完全兼容。
需要注意的是浏览器的安全沙箱:大多数数据库使用非标准端口上的非标准协议,而浏览器不支持这些协议。Azure Cosmos DB 是一个例外,因为它提供了通过 HTTPS 直接访问 API 的选项。
EF Core Azure Cosmos DB 提供程序可以直接从浏览器中运行的客户端访问数据库。但是,这也有局限性。在客户端存储凭据(即使是加密凭据)是不好的做法。您必须假定客户端有权访问,并且信息可能会导致您的数据库完全暴露。
为了安全访问,请使用 Azure Active Directory 等提供程序来保护用户的身份。然后,您可以通过请求具有安全限制的 Azure Cosmos DB 资源令牌来代替使用您的密钥。
阅读 EF Core 和 Azure Cosmos DB 与 Blazor WebAssembly 以了解更多信息。
渐进式 Web 应用
交付跨设备工作并提供原生体验的应用程序通常很困难。渐进式 Web 应用 (PWA) 提供了“全方位最佳”的解决方案。
PWA 使用一种称为服务工作线程的特殊基于浏览器的功能,使 Web 应用能够离线运行。像在手机、桌面或平板电脑上安装普通应用一样安装这些应用。当没有活动连接时,它们的代码会从本地存储加载页面。它们还支持推送通知,因此您的用户不会错过重要事件。
Blazor WebAssembly
应用模板有一个 checkbox
来启用 PWA。从命令行,只需使用 --pwa
开关,如下所示:
dotnet new blazorwasm --pwa -o pwa
创建新项目后,您会在 **wwwroot** 下看到特定的文件。
- manifest.json 是一个特殊的配置文件,它描述了您的应用以及安装时使用的各种图标的位置。
- 模板附带了几个图标。
- service-worker.published.js 脚本包含启用离线模式的特殊代码。
基本的 PWA 应用在用户浏览网站时将页面存储在本地存储中。它预先安装了必要的页面,并拦截浏览器获取页面的机制。当用户离线时,拦截代码会从缓存加载页面,并在用户在线时刷新缓存。当您运行应用程序时,现代浏览器会提供安装它的选项。
下图显示了 Microsoft Edge 中的图标和操作。
安装 PWA 应用会将其添加到您的应用程序列表,放置一个运行它的图标,并在无边框窗口中启动它,该窗口看起来像下图:
尽管应用程序有自己的窗口(可以移动和调整大小),但它是一个专用于运行 PWA 的浏览器版本。
CSS 隔离
最新的 Blazor 版本具有 CSS 隔离功能。像 Angular 和 React 这样的单页应用框架大量使用这一强大功能。
CSS 隔离使您可以单独设置每个组件的样式,而不是被迫管理整个应用的一个大型 CSS 库。无需为每种组件类型想出唯一的名称。如果您为“组件 A”设置标题元素的样式,它仅适用于该组件,而不会与其他“组件 B”冲突。
默认的 Blazor 项目模板会生成 CSS 隔离的示例。要创建与组件隔离的样式表,只需创建一个与组件同名并带有 .css 扩展名的文件。在默认的 Blazor 模板中,请注意 MainLayout.razor 有一个名为 MainLayout.razor.css 的关联文件。该文件中定义的样式仅适用于 MainLayout
组件。
要查看其工作原理,请注意,当您运行应用程序时,它会引用一个遵循 appname.styles.css 约定的文件。下图显示了检查名为“pwa
”的应用程序的网络调用的结果。
打开文件会显示此代码片段:
/* /Shared/MainLayout.razor.rz.scp.css */
.page[b-o6yozaou6y] {
position: relative;
display: flex;
flex-direction: column;
}
.main[b-o6yozaou6y] {
flex: 1;
}
请注意,样式现在有一个唯一的后缀,以避免与其他组件发生冲突。有关 CSS 隔离的完整详细信息,请阅读 ASP.NET Core Blazor CSS 隔离。
虚拟化
商业应用程序通常处理大量数据列表。分页不总是选项或最佳解决方案,但大型列表可能会因渲染列表组件的开销而降低性能。另一方面,用户在任何给定时间只使用一部分数据。即使列表包含数十万个元素,应用程序一次也只显示几十个。
虚拟化利用这一点来仅渲染可见组件。对于包含 500,000 个元素的列表,应用程序仅渲染视图中的 50 个元素。当用户滚动列表并且其他元素进入视图时,应用程序会渲染它们。处理的总时间是相同的,但将渲染延迟到项目滚动到视图中会给用户留下性能提升的印象。
在 Blazor 应用中,虚拟化非常容易实现。考虑一个显示食物项列表的 FoodItem
组件。典型的列表可能像这样渲染(注意使用 @key
属性来帮助 Blazor 跟踪列表项):
<div style="height:500px;overflow-y:scroll">
@foreach (var foodItem in foods)
{
<FoodItem @key="foodItem.Id" Item=”@foodItem” />
}
</div>
要虚拟化此组件,以便应用程序仅渲染视图中的项目,只需将列表包装在 Virtualize
组件中即可。
<div style="height:500px;overflow-y:scroll">
<Virtualize Items="@foods">
<FoodItem @key="context.Id" Item="@context" />
</Virtualize>
</div>
一些虚拟化指南与如何调整组件大小有关。您还可以指定一个委托来提供流式传输的项目。阅读 ASP.NET Core Blazor 组件虚拟化 以了解有关虚拟化的更多信息。
服务器端预渲染
一个常见的单页应用程序挑战是服务网页和渲染数据之间的延迟。页面模板必须先加载,然后是用于获取和渲染数据的异步操作。这可能导致用户体验不佳。
服务器端预渲染通过在服务器上构建虚拟文档对象模型 (DOM) 然后将其作为静态内容交付来解决此问题。然后,客户端应用程序接管。这为最终用户创造了无缝的体验。预渲染还可以通过提供可供搜索引擎索引的内容来提高您网站的搜索引擎优化 (SEO)。
要使预渲染正常工作,应用程序必须已托管。静态网站没有预渲染的服务器功能。ASP.NET Core 托管的应用程序可以托管 Blazor WebAssembly
以在首次加载时渲染组件的第一页。文档 预渲染和集成 ASP.NET Core Razor 组件 详细介绍了配置步骤。
您不必满足于在响应 HTTP 请求时进行运行时预渲染。您的应用程序可以在构建过程的 M 部分预渲染,并交付一组代表初始网站状态的静态资产。通过阅读 预渲染 Blazor WebAssembly 以优化搜索引擎 来了解有关此方法的更多信息。
热重载
Blazor 最热门的新功能之一,也是此列表中的第一项,是热重载。Web 开发是迭代的,生产力取决于尽快看到增量更改的结果。 .NET 团队不仅实现了此功能,还使其速度极快。如果您在以前的版本中使用过重载,请抛开您的期望,因为您必须亲眼看看更新后的重载。
新的热重载功能可在 .NET 6 预览版 3 中使用。请务必下载并安装该 .NET 版本以利用性能改进。
.NET 5 中的功能需要重新编译并重新加载整个应用程序,这要慢得多。使用
dotnet --version
运行它时,我们看到:
6.0.100-preview.3.21202.5
让我们来看一下热重载的实际效果。创建一个名为 HotReload
的新 Blazor 项目。
dotnet new blazorwasm -o HotReload
转到目录:
cd HotReload
在您喜欢的编辑器(如 Visual Studio (VS) 或 Visual Studio Code)中打开项目(如果您使用 Visual Studio,请确保使用 v16.9 或更高版本)。在属性下,找到并打开 launchSettings.json 文件。
在您选择的 Web 服务器下(默认是 IIS Express 或您的应用程序名称),添加属性 hotReloadProfile
,其值为 blazorwasm
。我们的看起来像这样:
{
"iisSettings": {
// cutting this out for brevity
},
"profiles": {
"IIS Express": {
// ignore this for now
},
"hotreload": {
"hotReloadProfile" : "blazorwasm",
"commandName": "Project",
"dotnetRunMessages": "true",
"launchBrowser": true,
// etc. etc.
}
}
}
保存您的更改。从命令行,使用新的 watch 命令,然后是标准 run 命令运行:
dotnet watch -- run
如果设置正确,第一条消息应指出热重载已激活。在应用程序运行时,请在您喜欢的集成开发环境 (IDE) 中打开项目或使用记事本打开页面。
转到 Pages,然后是 Index.razor,将“Hello, world!
”更改为“Hello, live refresh!
”,然后保存。您应该看到应用程序重新启动并加载新内容。第一次总是较慢,所以接下来,通过在“Welcome to your new app
”后面添加“friend
”来编辑该文本。保存它,您应该几乎立即看到类似下图的结果:
您可以在 .NET 6 预览版 3 发布说明 中了解有关此功能的更多信息。