查看: 90|回复: 0

Blazor 实战 1:开始你的Blazor之旅(1)

[复制链接]

2

主题

9

帖子

12

积分

新手上路

Rank: 1

积分
12
发表于 2023-1-19 11:03:50 | 显示全部楼层 |阅读模式
我们生活在激动人心的时代,因为 .NET 开发人员的生活从未如此美好。 我们可以为任何操作系统创建应用程序,无论是 Windows、Linux、iOS、Android 还是 macOS,当然,我们可以使用 ASP.NET MVC、Razor Pages 和 Web API 构建令人惊叹的基于 Web 的应用程序,这允许 多年来,我们致力于创建强大的可扩展且可靠的系统。
然而,长期以来一直缺少一块拼图。 所有 ASP.NET 的 Web 解决方案的一个共同点是它们都是基于服务器的。 我们从未能够利用 C# 和 .NET 的强大功能来编写客户端 Web 应用程序; 这一直是 JavaScript 的领域——但现在不是了。
在本章中,我将向您介绍一个名为 Blazor 的革命性客户端框架。 Blazor 基于 Web 标准构建,允许我们使用 C# 和 .NET 编写丰富、引人入胜的用户界面。 我们将探索 Blazor 如何使您的开发过程更高效并提高您的生产力水平,尤其是当您也在服务器上使用 .NET 时。 我们将介绍托管模型,这是开始使用 Blazor 时需要了解的一个重要概念。 接下来,我们将开始探索组件以及使用它们构建 UI 的好处。 最后,我们将讨论下一个项目应考虑使用 Blazor 的原因。
1.1 新应用为什么选择Blazor?
可以说,最近开始一个新项目最困难的部分是选择技术堆栈——可供选择的选择太多了。 在前端世界中尤其如此。 我们必须选择一个框架(Angular、React、Vue.js),选择一种语言(TypeScript、CoffeeScript、Dart),并选择一个构建工具(webpack、Parcel、Browserify)。 如果一个团队是这个生态系统的新手,那么尝试找出哪种技术组合将有助于项目成功似乎是一项几乎不可能完成的任务; 有经验的团队更难!
让我们介绍为您的下一个项目选择 Blazor 的一些主要原因,以及 Blazor 如何帮助您避免我刚才提到的一些问题。
C#,一种功能丰富的现代语言——Blazor 由 C# 提供支持,根据 2021 年 Stack Overflow 开发人员调查 (http://mng.bz/p240),C# 是第八大最流行的语言。 它功能强大、易于学习且用途广泛。 虽然 C# 是一种面向对象的语言,但如果您愿意,它正在采用越来越多的功能来实现更实用的方法。 静态类型帮助开发人员在构建时捕获错误,使开发生命周期更快、更高效。 它也已经存在了很长时间,目前是第十个版本。 它稳定、设计精良且支持良好。
出色的工具——.NET 社区很幸运拥有一些出色的工具。 Visual Studio 是一个极其强大、功能丰富且可扩展的 IDE(集成开发环境)。 对于个人、开源工作或最多五人的非企业团队,它也是 100% 免费的。 如果您更喜欢轻量级的东西,那么可以使用 Visual Studio Code (VS Code),它是当今最流行的代码编辑器之一。 Visual Studio 和 VS Code 都可以跨平台使用。 Visual Studio 适用于 Windows 和 macOS,而 VS Code 适用于 Windows、macOS 和 Linux。 JetBrains 还有一个很棒的第三方 IDE,称为 Rider,它是跨平台运行在 Windows、macOS 和 Linux 上的。

.NET 生态系统——虽然许多新框架需要等待围绕它们构建的生态系统,但 Blazor 可以利用现有的 .NET 生态系统。 在撰写本文时,Blazor 应用程序以 .NET 6 为目标,理论上可以使用任何兼容的 NuGet 包。 我说“理论上”,因为一些包执行 WebAssembly 场景中不允许的操作,例如修改文件系统。

不拘一格——虽然其他框架规定了应用程序必须如何编写,但 Blazor 没有。 Blazor 开发没有首选模式或实践; 您可以使用您熟悉和熟悉的应用程序来编写应用程序。 如果您喜欢 MVVM(模型-视图-视图模型),那就去吧。 如果你更喜欢使用 Redux,那就试试吧。 这是你的选择。

浅学习曲线——如果您是现有的 .NET 开发人员,那么 Blazor 的学习曲线非常浅。 Razor、C#、依赖项注入和项目结构对您来说都很熟悉,并且由于 Blazor 对模式没有意见,您可以只使用您熟悉且富有成效的东西。 所有这一切意味着您可以专注于更快地编写功能,而不是学习框架。

代码共享——如果你在服务器上使用 C#,那么 Blazor 是一个很好的搭配。 不同的客户端和服务器语言最令人沮丧的问题之一是无法重用代码。 模型或数据传输对象 (DTO) 必须在服务器和客户端之间复制; 他们需要保持更新,同步。 这可以是手动过程或使用某种代码生成自动进行,但这只是设置和维护的另一件事。 使用 Blazor,一切都是 C#。 任何共享代码都可以放在通用的 .NET 类库中,并在服务器和客户端之间轻松共享。

开源——与 Microsoft 的许多项目一样,Blazor 是完全开源的,代码在 GitHub 上免费提供,您可以浏览、下载或创建自己的副本。 该团队公开工作,并以开发人员的请求和反馈为指导。 如果你愿意,你甚至可以做出贡献。
1.2 组件,更好的UI构建方式
与许多现代前端框架一样,Blazor 使用组件的概念来构建 UI。 一切都是组件——页面、页面的一部分、布局。 Blazor 中有多种类型的组件,以及多种设计它们的方法,所有这些都将在以后的章节中进行探讨。 但学习从组件的角度思考对于编写 Blazor 应用程序至关重要。
1.2.1 什么是组件?
将组件视为构建块。 您将这些构建块放在一起以形成您的应用程序。 这些构建块可大可小,由您决定; 但是,将整个 UI 构建为单个组件并不是一个好主意。 当用作划分 UI 逻辑区域的方式时,组件真正显示出它们的优势。 让我们看一个由组件构成的用户界面示例(图 1.1)。



图 1.1 组件布局示例

界面的每个区域都是一个组件,每个区域都有一定的职责。 您可能还会注意到形成了一个层次结构。 布局组件位于树的顶部; 菜单、页眉、主页和页脚都是布局组件的子组件。 这些子组件可以并且很可能会有自己的子组件。 例如,标题组件可以包含徽标组件和搜索组件(图 1.2)。



图1.2 组件嵌套组成组件树示例

1.2.2 基于组件的 UI 的好处
许多 UI 中都有重复元素。 使用组件的一大优势是您可以在组件中定义一个元素,然后在元素重复的任何地方重用该组件。 这可以大大减少应用程序中重复代码的数量。 它还使应用程序的可维护性更好——如果该元素的设计发生变化,您只需在一个地方更新它。
为了迎合更高级的场景,组件可以定义自己的 API,允许数据和事件传入和传出。 想象一个业务线应用程序。 可以安全地假设在该应用程序中有许多地方以表格格式显示数据。 一种方法是将每个表创建为它自己的组件; 然而,这意味着我们最终会得到很多在表格中显示数据的组件。 更好的方法是定义一个单独的组件,将数据集作为参数,然后将其显示在表格中。 现在我们有了一个用于在表格中显示数据的组件,我们可以在整个应用程序中重复使用该组件。 我们也可以给这个组件添加功能,比如排序或者分页。 正如我们所做的那样,此功能自动可用于应用程序中的所有表,因为它们都重用了相同的组件。
虽然通常是独立的,但可以让组件协同工作以创建更复杂的 UI。 比如我们刚才讲的数据表场景,它可能是一个组件,但可能会很大。 另一种方法是将其分成几个较小的组件,每个组件执行特定的工作。 我们可以有一个表格标题组件、一个表格主体组件,甚至一个表格单元格组件。 这些组件中的每一个都执行特定的工作,但它们仍然是整个表组件的一部分。

1.2.3 Blazor 组件剖析
现在我们对一般意义上的组件有了更好的了解,让我们看一下 Blazor 中的组件示例。 为此,我们将从 Blazor 项目模板中获取一个组件。 图 1.3 显示了来自 Blazor 的标准项目模板 Counter.razor 的组件示例。



图 1.3 Blazor 中组件的部分

这个特定的组件被称为可路由组件,因为它有一个在顶部声明的页面指令。 可路由组件本质上是应用程序中的一个页面。 当用户导航到应用程序中的 /counter 路由时,该组件将由 Blazor 路由器加载。 它显示一个带按钮的简单计数器,当用户单击该按钮时,计数加一,并将新值显示给用户。
虽然此时理解代码并不重要,但我们可以理解组件的结构。 图 1.3 分为三个部分; 每个人都有一定的责任。
第 1 部分——用于定义指令、添加 using 语句、注入依赖项或适用于整个组件的任何其他通用配置。
第 2 节——定义组件的标记; 这是使用 Razor 语言编写的,它是 C# 和 HTML 的混合体。 在这里,我们定义了构成组件的视觉元素。
第 3 节——代码块。 这用于定义组件的逻辑。 可以将任何有效的 C# 代码写入此部分。 如果愿意,您可以定义字段、属性甚至整个类。
我们将在本书的其余部分更详细地介绍组件,因此我们暂时将其留在那里。 但这让您了解了 Blazor 中的组件是什么样子以及它是如何组成的。
1.3 Blazor,一个使用 C# 构建现代 UI 的平台
Blazor 是一个功能齐全的框架,用于使用 C# 和 .NET 的强大功能构建现代客户端应用程序。 这使开发人员能够构建可在几乎任何平台(包括 Web、移动和桌面)上运行的引人入胜的应用程序。
Blazor 是 JavaScript 框架和库(如 Angular、Vue.js 和 React)的替代品。 如果您有使用其中任何一个的经验,那么您可能会开始发现熟悉的概念。 最显着的影响是使用组件构建 UI 的能力,这是所有这些技术共享的概念,我们将在本章后面更详细地探讨。
因为 Blazor 是建立在 Web 标准之上的,所以它不需要最终用户在他们的机器上安装 .NET 或任何类型的浏览器插件或扩展。 事实上,使用 Blazor WebAssembly 应用程序,我们甚至不需要在服务器上运行 .NET; 这种风格的 Blazor 可以作为简单的静态文件托管。
基于 .NET 构建意味着我们可以访问 NuGet 上可用的充满活力的包生态系统。 我们拥有一流的工具,包括 Visual Studio、VS Code 和 JetBrains Rider。 此外,由于 .NET 是跨平台的,我们可以在任何我们喜欢的平台上开发我们的 Blazor 应用程序,无论是 Windows、macOS 还是 Linux。
虽然本书将重点介绍用于 Web 应用程序开发的 Blazor,但我想强调的是,Blazor 的编程模型也可用于构建跨平台桌面应用程序。 在 .NET 6 中,引入了 Blazor Hybrid。 它建立在新的 .NET 多平台应用程序 UI(又名 MAUI)框架之上,其工作方式与 Electron 应用程序类似。 来自 Blazor 应用程序的内容通过 BlazorWebView 控件呈现。 这为这些应用程序的结构提供了很多选择。 开发人员可以使用 Blazor 和 Web 技术来构建整个 UI——chrome 除外,chrome 是包含标题栏的应用程序的最外层容器。 或者,他们可以仅针对要使用 Blazor 编写的特定界面部分,并将其与本机控件一起托管。
它不止于此。 有一个长期运行的实验项目,称为 Mobile Blazor Bindings (http://mng.bz/OGOO)。 这是 ASP.NET Core 团队和 .NET MAUI 团队之间的合作,旨在调查使用 Blazor 的编程模型构建原生移动应用程序的潜力和需求! 这确实使 Blazor 成为一项引人注目的学习技术,正如人们曾经理解的那样,它可以让开发人员为几乎任何平台或设备构建 UI。
希望您已经看到 Blazor 是一项令人兴奋的技术,具有很大的潜力。 但是,在我们进一步讨论之前,有一个关键概念很重要,即托管模型。 让我们接下来解决这个问题。
1.3.1 了解托管模型
第一次开始使用 Blazor 时,您会立即遇到托管模型。 本质上,托管模型是运行 Blazor 应用程序的地方。 目前,Blazor 有两种特定于 Web 的托管模型——Blazor WebAssembly 和 Blazor Server。 无论您为应用程序选择哪种模型,组件模型都是相同的,这意味着组件的编写方式相同,并且可以在任一托管模型之间互换(图 1.4)。



图 1.4 Blazor 将托管模型与其应用程序/组件模型分开。 这意味着为一种托管模型编写的组件可以与另一种托管模型一起使用。

图 1.4 显示了 Blazor 架构的抽象表示,其中应用程序和组件模型与各种托管模型之间存在分离。 Blazor 的一个有趣方面是随着时间的推移可能会提供其他托管模型。 这使得 Blazor 可以在更多地方运行并用于创建更多类型的 UI。
1.3.2 Blazor WebAssembly
Blazor WebAssembly 允许您的应用程序完全在客户端浏览器内运行,使其成为 JavaScript SPA(单页应用程序)框架的直接替代方案。 为了帮助您了解此托管模型的工作原理,我们将介绍初始化 Blazor WebAssembly 应用程序的过程(图 1.5)。



图 1.5 Blazor WebAssembly 应用程序的启动显示了客户端浏览器和 Web 服务器之间的交互

当浏览器向 Web 服务器发出请求时,该过程就开始了。 Web 服务器将返回加载应用程序所需的一组文件。 其中包括应用程序的主页,通常称为 index.html; 应用程序所需的任何静态资产,例如图像; CSS 和 JavaScript,以及一个名为 blazor.webassembly.js 的特殊 JavaScript 文件。
在 Blazor WebAssembly 托管模型中,部分 Blazor 框架驻留在 JavaScript 中并包含在 blazor.webassembly.js 文件中。 框架的这一部分主要做了三件事:
在浏览器中加载并初始化 Blazor 应用程序
提供直接的 DOM(文档对象模型)操作,以便 Blazor 可以执行 UI 更新
提供 JavaScript 互操作场景的 API,我们将在后面的章节中详细讨论
此时,您可能想知道为什么我们有一个 JavaScript 文件。 Blazor 的一大卖点是能够使用 C# 而不是 JavaScript 编写 UI 逻辑,对吧? 是的,这是真的。 但就目前而言,WebAssembly 有一个很大的局限性:它不能改变 DOM 或直接调用 Web API。 这些功能已为 WebAssembly 的下一阶段进行了规划和开发,但在它们落地之前,JavaScript 是执行这些任务的唯一方式。
将来可能不再需要此文件。 这将取决于功能添加到 WebAssembly 和被浏览器采用的速度有多快。 但就目前而言,它是框架的重要组成部分。
现在我们已经清除了它,让我们回到启动 Blazor 应用程序。 需要指出的是,服务器返回的文件都是静态文件; 他们不需要任何服务器端编译或操作。 这意味着它们可以托管在任何提供静态托管的服务上。 服务器上不需要 .NET 运行时。 这是第一次向 .NET 开发人员开放免费托管选项,例如 GitHub 页面(这仅适用于独立的 Blazor WebAssembly 应用程序)。
一旦浏览器从 web 服务器接收到所有初始文件,它就可以处理它们并构建 DOM。 接下来,执行 blazor.webassembly.js。 这会执行许多操作,但在启动 Blazor WebAssembly 应用程序的上下文中,它会下载一个名为 blazor.boot.json 的文件。 此文件包含运行应用程序所需的所有框架和应用程序文件的清单。 下载后,它用于下载运行应用程序所需的剩余文件。
这些文件中的大多数都是普通的 .NET 程序集; 它们没有什么特别之处,它们可以在任何兼容的 .NET 运行时上运行。 但还有另一种类型的文件被下载,称为 dotnet.wasm。 此文件是已编译为 WebAssembly 的完整 .NET 运行时。
WebAssembly
WebAssembly 是一种低级的、类似汇编的语言,可以在现代网络浏览器中运行,具有接近本机的性能。 尽管可以直接编写 WebAssembly,但它更常用作 C/C++ 和 Rust 等高级语言的编译目标。 它旨在与 JavaScript 一起运行,允许 JavaScript 调用 WebAssembly,反之亦然。 WebAssembly 还与 JavaScript 应用程序在相同的安全沙箱中运行。 有关 WebAssembly 的详细信息,请访问 https://webassembly.org。
默认情况下,只有 .NET 运行时被编译为 WebAssembly——框架和应用程序文件是标准的 .NET 程序集。 然而,在 .NET 6 中,引入了 AOT(提前)模式,允许开发人员将他们的应用程序编译为 WebAssembly。 这样做的好处是大大提高了 CPU 密集型代码的性能。 使用 AOT,编译为 WebAssembly 的 CPU 密集型代码的性能将比默认使用的解释方法高出许多倍。 然而,有一个权衡,那就是大小。 AOT 编译的代码大约是标准程序集的两倍,这意味着应用程序的整体下载大小要大得多。
下载 blazor.boot.json 文件并下载其中列出的文件后,就可以运行应用程序了。 WebAssembly .NET 运行时被初始化,它依次加载 Blazor 框架,最后加载应用程序本身。 此时,我们有一个正在运行的 Blazor 应用程序,它完全存在于客户端的浏览器中。 除了请求额外的数据(如果适用)之外,不再依赖服务器。
计算 UI 更新
我们现在了解了 Blazor WebAssembly 应用程序是如何启动的。 但是如何计算 UI 更新呢? 正如我们在初始化过程中所做的那样,我们将遵循一个场景来了解这是如何发生的以及 Blazor 做了什么(图 1.6)。



图 1.6 Blazor WebAssembly 中客户端导航的过程,从点击链接到应用 UI 更新

对于我们的场景,我们有一个 Blazor WebAssembly 应用程序,其中有两个页面仅包含一个标头:分别是 Home 和 Counter。 用户在应用程序的主页上,将单击链接转到计数器页面。 我们将遵循 Blazor 在从主页导航到计数器页面时更新 UI 的过程。
当用户单击计数器链接时,导航事件被 Blazor 的 JavaScript 运行时 (blazor.webassembly.js) 拦截。 然后,此事件将传递到在 WebAssembly 运行时 (dotnet.wasm) 上运行的 Blazor 框架,并由 Blazor 的路由器组件进行处理。
路由器检查其路由表以查找与用户尝试导航到的路由相匹配的任何可路由组件。 在我们的例子中,它将找到与 Counter 组件的匹配项,将创建该组件的一个新实例,并执行相关的生命周期方法。
完成后,Blazor 将计算出更新 DOM 以匹配计数器组件所需的最少更改数。 完成后,这些更改将传递回 Blazor JavaScript 运行时,然后将这些更改应用到物理 DOM。 此时,UI 将更新,用户将进入计数器页面。
所有这些都发生在用户浏览器的客户端。 在此过程中的任何时候都不需要服务器。 可以公平地说,在真实世界的应用程序中,您可能会在此过程中的某个时刻调用服务器。 这通常发生在执行被导航到的组件的生命周期方法期间,以便为组件加载一些初始数据。 但这将取决于个别应用程序。
好处和权衡
现在我们对 Blazor WebAssembly 托管模型的工作原理有了更多的了解,让我们来谈谈选择这种模型的好处和权衡。 让我们从好处开始:
应用程序在客户端运行——这意味着服务器上的负载要少得多,因此您可以将大部分工作卸载给客户端。 这可以显着节省服务器基础设施的成本并提高应用程序的可扩展性。
可以在离线场景中工作——由于应用程序完全在浏览器中运行,因此不需要与服务器的持久连接,从而使应用程序更能容忍不稳定的网络连接。 启用渐进式 Web 应用程序 (PWA) 功能也很简单。 事实上,Blazor WebAssembly 将此作为您在创建应用程序时可以选择的选项。
部署为静态文件——由于 Blazor WebAssembly 应用程序只是静态文件,因此可以将它们部署在任何可用静态托管的地方。 这打开了一些选项,这些选项在历史上从未对 .NET 开发人员可用。 GitHub 页面、Netlify、Azure Blob 存储、AWS(亚马逊网络服务)S3 存储桶和 Azure 静态 Web 应用程序等服务都是托管独立 Blazor WebAssembly 应用程序的选项。 与在每个领先的云提供商中托管 Web 应用程序相比,部署静态文件的成本相对较低。
代码共享——如果您在服务器上使用 C#,Blazor WebAssembly 的最大好处之一可能是。 您现在可以在客户端上使用与在服务器上使用的相同的 C# 对象。 保持 TypeScript 模型与其等效的 C# 模型同步的时代已经结束,反之亦然。
当然,没有什么是灵丹妙药,所以让我们了解一下这个模型的一些权衡:
负载——与某些 JavaScript 应用程序相比,Blazor 应用程序的初始下载大小可能要大得多(尽管每个版本都在改进)。 可以生成最小的 Blazor 应用程序,发布时重量约为 1 MB; 但是,其他应用程序可能会大得多。 每个应用程序都是不同的,Blazor 应用程序没有标准大小。 不过,这是一次性成本,因为运行时和许多框架程序集都在第一次加载时缓存,这意味着后续加载可能只有几 KB。
加载时间——负载大小的连锁反应可能是加载时间。 如果用户的互联网连接状况不佳,下载初始文件所需的时间会更长,这会延迟应用程序的启动,给用户留下某种加载消息。 这可以通过使用服务器端预渲染稍微抵消; 然而,虽然这会给用户带来一些更有趣的东西,但在所有文件下载和初始化之前,应用程序仍然无法交互。 Blazor WebAssembly 应用程序的服务器端预呈现还需要服务器上的 ASP.NET Core 元素,这会否定任何免费托管选项。
受限的运行时间——这可以说不是一种权衡,但对于习惯于相对自由地控制其应用程序运行的机器的现有 .NET 开发人员来说,这是需要注意的事情。 WebAssembly 应用程序与 JavaScript 应用程序在相同的浏览器沙箱中运行。 这意味着,例如,您将无法访问用户的计算机并执行诸如访问本地文件系统之类的操作。
代码安全——与 JavaScript 应用程序一样,您的代码在浏览器中下载和运行。 因此,用户可以访问您的应用程序 DLL。 这意味着您不应在 Blazor WebAssembly 应用程序中包含任何包含知识产权的代码。 任何有价值的代码都应该作为 API 的一部分保存在服务器上。
总而言之,如果您要替换 Angular、React 或 Vue.js 等 JavaScript SPA 框架,Blazor WebAssembly 是可供选择的托管模型。 虽然需要考虑一些权衡,但选择此模型有一些实质性的好处。
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

快速回复 返回顶部 返回列表