2018 年 9 月
33 卷,第 9
此文章由机器翻译
领先技术-么更别提 JavaScript,此处的 Blazor
大概十年前主流 Web 鉴定处停止。传统上解释客户端技术,如 HTML、 CSS 和 JavaScript 是以消失,以渐进方式因编译的技术和 XAML 和 C# 等语言。在同一时间,似乎随时可以合并本机,在浏览器环境专用接近 Silverlight,已安装为一个单独的插件的处理引擎。然后出现在即将推出的 HTML 5 的第一个草稿并此后不久,Silverlight 的 sunsetted。
如 IT 决策制定者查找适用于跨平台 Web 开发平台的可行性的事件的启用震动向上布局。HTML5 收到提升和 JavaScript 开始其实现重生。今天,Angular、 React 和 Vue 非常越来越多的开发团队选择生成其前端的非常受欢迎的基于 JavaScript 的框架。
作为 Angular/React/Vue 的可能替代 Blazor 出现和得益于 WebAssembly (WASM),它会打开 Web 能够充分利用现有开发生态系统,包括.NET。因此,多个只是另一个模型-视图-视图模型 MVVM 面向 JavaScript 框架,Blazor 是,在某种程度上的现代尝试改进和完善 Silverlight 概念 — 将 C# 的强大功能引入到客户端的 Web 开发。Blazor 核心专为提供了构建 Web 前端使用 C# 和.NET Core,而不是 JavaScript 和 HTML 基于 Razor 的强类型化的、 基于浏览器的环境。但是,Blazor 不到角推送 HTML 和 CSS。相反,它扩展了一系列预定义 Razor 标记帮助程序同时不需要任何插件安装 HTML 语法。
我不建议 Blazor 仍很大程度上处于开发阶段和任何你此处要读取可能会从根本上更改仅几周之后。在本文中提供的代码基于版本 0.5.0 在 2018 年 7 月发布。
在本文中,我将讨论 Blazor 应用程序的基础系统体系结构,提供最小"Hello World"应用程序。
神奇的 Blazor
如果来自 Silverlight 背景,您可能想要知道如何 Blazor — 非 JavaScript 平台,可以浏览器中运行而无需安装插件。答案是,嗯,它不能。Blazor 实际上需要某种形式的插件,以符合标准的浏览器中托管它。其奥妙在于所谓概念插件已嵌入在大多数新式浏览器 (即在过去的 12 个月发布),可以轻松地为旧版浏览器中的通过 JavaScript polyfilled。启用 Blazor 支持该工具与离散插件如 Adobe Flash 或 Silverlight,WASM,包括所有主要浏览器的客户代表现有的 W3C 社区组中开发的开放标准。
从技术上讲,WASM 是基于堆栈的虚拟机 (VM) 体系结构上类似于.NET CLR 和 Java 虚拟机,但与 Android Dalvik VM 不同的二进制格式。作为高级编程语言的编译目标,WASM 有可能使通过 Web 部署.NET 应用程序。这种情况发生,但是,桥需要将.NET 运行时转换为 WASM。Blazor 完全依赖于由 Xamarin 以使其 Mono 框架 WASM 完成工作。Blazor 应用程序中包含的.NET 代码在运行 Mono 到 WASM,特别是编译的版本,如中所示图 1。
图 1 在浏览器中运行的.NET 代码
这是如何不同于说,Silverlight?Silverlight 应用程序运行在与容器浏览器环境中,通过在 Internet Explorer 中,ActiveX 和 NPAPI 在 Chrome 和 Firefox 等其他浏览器通信的特定于浏览器的 shell 中沙盒 (请参阅文档: bit.ly/2klDgdY)。今天,大多数浏览器解除 NPAPI 支持以 WebAssembly 支持。Blazor 采用的许多最佳 Silverlight 的概念,并将其应用到开发人员可以利用 JavaScript 的替代方法很感兴趣的方式。
旧的浏览器如何呢?
开发工具到这两个 WASM 交叉编译代码并 asm.js,这是 JavaScript 的低级别子集,是从高级语言编译目标 (请参阅asmjs.org)。Blazor,特别是,将回退使用 asm.js 基于.NET 运行时。然后已部署的代码执行功能检测以确定如何运行在浏览器中。请注意,整个 asm.js 框架目前正在研究和开发。
您可以访问caniuse.com来检查哪种浏览器版本,目前支持 WASM。站点说明,所有浏览器版本 (桌面和移动版) 发布从 2017 年中旬和支持它。请注意,在撰写本文时,Internet Explorer 暂时未使用 Blazor 填充代码。
Blazor 应用程序剖析
Blazor 应用程序是一个 Program.Main 入口点,获取下载和运行在浏览器中的普通.NET Standard 库。只有.NET 运行时编译为 WASM;就像普通的.NET 应用程序,在 C# 中编写的源代码以本机方式运行。若要清除安全问题,请注意所有 Blazor 代码仍在 JavaScript 同样的安全沙箱中都运行。图 2显示的文件下载本文的其余部分中显示的示例 Blazor 应用程序的列表。
图 2 示例 Blazor 应用程序下载的文件
图中所示的不同的背景颜色标识 Blazor 应用程序的生存期中的两个不同时刻。首先,下载 blazor.js 和 mono.js 文件来协调下载 Mono WebAssembly 运行时 (mono.wasm 文件)。目前,Mono 运行时包括相对功能丰富版本的.NET 和天知道 600 KB。但是,在早期版本 compact 选项提供的大小的一小部分。这是可以使用一些改善和优化的区域。
一旦下载 Mono 运行时,它将开始实际.NET 程序集的下载。初始化步骤可能需要一段时间 — 的示例中大约三秒图 2。出于此原因,标准 Blazor Visual Studio 模板提供了 UI 以显示在加载阶段的专用的区域。让我们看看一个示例应用程序。
构建示例应用程序
若要播放使用 Blazor,需要.NET Core 2.1 和 Visual Studio 15.7 或更高版本。此外,您需要从 Visual Studio marketplace 安装 Blazor 模板。该模板位于 ASP.NET Core Web 应用程序文件夹下。目前有三个模板 — 纯客户端 Blazor、 ASP.NET Core 托管的应用程序和服务器端 Blazor。让我们使用不依赖于任何后端环境为普通 Blazor 应用程序。这种情况下很密切的关系类似于 Angular/React 或甚至 Silverlight 应用程序,下载并运行在浏览器中的普通客户端应用程序。
如前文所述,Visual Studio 中的项目是基于两个特定的 NuGet 包的.NET Standard 2.0 控制台应用程序:Blazor.Build 和 Blazor.Browser。两者的根源在于 Microsoft.AspNetCore 命名空间。
项目是一个标准的.NET Core 项目 Program.cs 引导程序、 Startup.cs 类,与重新调用 ASP.NET Core 应用程序,例如 wwwroot、 共享和页的几个文件夹。Main 方法中所示,如下所示:
public class Program
{
public static void Main(string[] args)
{
CreateHostBuilder(args).Build().Run();
}
public static IWebAssemblyHostBuilder CreateHostBuilder(string[] args) =>
BlazorWebAssemblyHost.CreateDefaultBuilder()
.UseBlazorStartup<Startup>();
}
Blazor 应用程序由组件的每个包含.cshtml Razor 文件。默认情况下,.cshtml 文件的名称为组件的名称。在示例应用程序,应用程序是其源代码位于 app.cshtml,启动组件的名称,如下所示:
<Router AppAssembly=typeof(Program).Assembly />
最小值,startup 类指示要使用的应用程序类。
public class Startup
{
public void Configure(IBlazorApplicationBuilder app)
{
app.AddComponent<App>("app");
}
}
应用程序模块只需设置 Blazor 路由器组件。在传统的 Web 站点 (如 ASP.NET),路由会发生在服务器上,但在单页面应用程序中它最好是通过专用的客户端组件。在 Blazor,路由器不进行 JavaScript (因为它是在中,即 Angular),但是,而不是,是分析中引用的程序集,寻找那些实现 IComponent 接口的所有类的内部路由器类的实例。
该路由器是负责截获所有的导航活动,向内和向外,并使这种情况。很明显,Blazor 组件需要提供路由器以相应地调用它们的路由信息。Blazor 支持 ASP.NET Core 中 Razor 页面的相同 @page 表示法。此外,它以纯 C# 编写的组件类支持路由特性。
单个页面
通常情况下,从 index.html 页开始的单页面应用程序。Blazor 应用程序也不例外,并且单个页面位于 wwwroot 文件夹下。单个页面应至少包含以下标记:
<app>
<!—initialization markup -->
</app>
<script src="_framework/blazor.webassembly.js"></script>
应用元素的内容显示在 Blazor 平台,即第一个区块的列表中的文件的初始加载期间图 2。您可以任意有效的 HTML 在应用程序元素中,最常加载.gif。Script 元素负责进行动态下载必要的.dll 文件。
主页的实际显示的内容由路由器、 index.html 文件的其余内容中发现包含以下的脚本元素。让我们查看路由器完成的工作。
路由器检查请求的 URL-已部署站点的根,并查找已注册的组件可以与匹配的根 URL。在示例项目中,页文件夹包含一个 index.cshtml 文件,以包含以下内容:
@page "/"
<h1>Hello, Blazor!</h1>
Welcome to your first BLAZOR app.
@Page 指令指示要提取的模板有关路由器。如果存在于 _ViewImports.cshtml 文件位于 Pages 文件夹 (和/或根文件夹),其内容纳入考虑。在示例项目中,根文件夹中的 _ViewImports 文件包含 using 语句,而页面文件夹中的 _ViewImports 文件包含对布局模板的引用的列表:
@layout MainLayout
随后,处理 MainLayout.cshtml 内容和 @Body 占位符填充与所选的 Razor 视图 (index.cshtml) 的输出。在示例项目中,布局文件 (位于共享文件夹,如 ASP.NET Core 中所示) 包含一个典型的 Bootstrap 4 深色导航栏元素。下面是该代码:
<nav class="navbar navbar-expand-lg navbar-dark bg-dark">
...
</nav>
<div class="container">
@Body
</div>
同样,如果您要来自 ASP.NET MVC 背景时,此编程模式感到很熟悉。在导航栏中通常具有链接。可以表示通过规范 A 和按钮元素,或使用预定义的 (或自定义) 的链接的 Razor 标记帮助程序。具体而言,Blazor 附带 NavLink 帮助程序组件,它提供更友好的语法来表达可能或可能不是普通的 Url 的链接。在单页面应用程序中,实际上,一个链接可以是路由器可以理解的任何内容。下面是在导航栏中的示例应用程序中使用的 Razor 代码的片段:
<div class="collapse navbar-collapse" id="navbarNav">
<ul class="navbar-nav">
<NavLink class="nav-link" href="digitalclock">
DIGITAL CLOCK
</NavLink>
</ul>
</div>
Href 属性指向一个 URI,它只是匹配路由到"digitalclock,"完全实现了一个数字时钟组件的单独 CSHTML 文件等组件。在页面文件夹下找到 digitalclock.cshtml 文件。
生成组件的示例
Blazor 组件是自包含的 HTML 和 C# 块。任何必要的 CSS 会在单独的文件,以合理方式命名组件本身。请注意,Blazor 不执行任何特定 CSS 操作不会施加任何约定。CSS 处理是完全取决于您。下面是一个实现为 Bootstrap 输入组的数字时钟:
<div class="clock">
<div class="input-group">
<span class="@currentCss">@currentTime</span>
<div class="input-group-append">
<button class="btn btn-primary"
type="button"
onclick="@startStop">@buttonAction</button>
</div>
</div>
</div>
CurrentCss、 currentTime 等 buttonAction razor 表达式引用组件字段内文件的 @functions 部分定义。您可以在此处看到这些:
@functions {
string currentTime = "N/A";
string buttonAction = "N/A";
string currentCss = "clock-notset";
Timer timer;
...
}
StartStop 表达式是指当单击停止或开始按钮以启动/停止计时器时调用的方法。图 3展示了 DigitalClock 组件的完整代码。
图 3 C# 代码的 DigitalClock 组件
@functions {
string currentTime = "N/A";
string buttonAction = "N/A";
string currentCss = "clock-notset";
Timer timer;
protected override async Task OnInitAsync()
{
InitTimer();
StartTimer();
}
void startStop()
{
if (timer.Enabled)
{
StopTimer();
}
else
{
StartTimer();
}
}
private Task TimerTick()
{
currentTime = DateTime.Now.ToLongTimeString();
currentCss = "clock-working";
this.StateHasChanged();
return Task.CompletedTask;
}
private void InitTimer()
{
timer = new Timer(1000);
timer.Elapsed += async (sender, e) => await TimerTick();
}
private void StartTimer()
{
buttonAction = "STOP";
timer.Start();
}
private void StopTimer()
{
buttonAction = "START";
timer.Stop();
}
}
图 4显示了程序接口。
图 4 操作中的应用程序示例
该演示显示数字时钟受.NET 计时器。数据绑定将自动进行显式用户操作 (例如单击按钮时),通过触发的事件,但不是时生成事件以编程方式,例如通过一个计时器。在后一种情况下,必须调用方法 StateHasChanged 强制浏览器呈现器,以刷新视图。下面是数字时钟 Blazor 组件中的计时器时钟周期处理程序的代码:
private Task TimerTick()
{
currentTime = DateTime.Now.ToLongTimeString();
currentCss = "clock-working";
this.StateHasChanged();
return Task.CompletedTask;
}
完整的源代码可从bit.ly/2LVeCxA。
总结
Blazor 是即将发布的实验性框架,用于构建。基于 NET 的单页面应用程序通过 WebAssembly 在浏览器中运行。WebAssembly 是沙盒办法将本机二进制文件部署到符合的浏览器,自 2017 年中旬以来提供实质上是所有浏览器。Blazor 到设计视图中使用 Razor 和 C#,并包含一个路由器和其他常用 JavaScript 框架的大多数类似的可组合的用户界面。
本文提供了客户端应用程序的基础。在即将发布的列,我将探讨与特定 ASP.NET Core 后端和 Blazor 扩展点的集成。你可以阅读更多有关在 Blazor Jonathan Miller 的文章,引导您完成从 HTTP 终结点中下载 JSON 数据的客户端应用程序非常必要的任务。
Dino Esposito在他 25 年的职业生涯中撰写了超过 20 本书籍和 1,000 篇文章。Esposito 不仅是舞台剧《事业中断》的作者,还是 BaxEnergy 的数字策略分析师,正忙于编写有助于建设环保世界的软件。可以在 Twitter 上关注他 (@despos)。
衷心感谢以下技术专家对本文的审阅:Daniel Roth (Microsoft)、 Jonathan Miller