一. 唠唠 webAssembly 的发展历程
目前有很多支持 WebAssembly 的项目, 但发展最快的是 Blazor, 这是一个构建单页面的. NET 技术, 目前已经从 Preview 版本升级到了 beta 版本, 微软计划在 2020 年 5 月发布 Blazor 的第一个版本.
Blazor 是什么? 它是一项将 C#和. NET 都放入浏览器的 Microsoft 技术. 它使用 WebAssembly 来工作, WebAssembly 是一种高性能的管道, 可以将代码预编译为紧凑的二进制格式. 最重要的是, 每个主流浏览器 (包括移动版本) 都支持 WebAssembly.
十年前, JavaScript 统治世界还不是很明显. Flash 和 Silverlight 也正在运行. 这二个都需要使用浏览器插件来完成工作, 并且都以不同的用户界面方法替换了 html. 这种方法使他们在功能方面遥遥领先于 JavaScript, 但随着移动互联网的出现, 他们就慢慢过时.
但随后从最初的 JavaScript 再到微软的 JScript 和 CEnvi 的 ScriptEase 三足鼎立, 再到最后的统一标准, 当时微软凭借 Windows 系统捆绑 Internet Explorer 的先天优势击溃 Netscape 后, 两大巨头就此进入了长达数年的静默期, JavaScript 就是在这样的情况下被构想出来的, 当时的浏览器之王, Netscape Navigator 创始人 Marc Andreessen 认为 Netscape 需要一种 "glue language" 来支持 HTML, 让 Web 设计师和兼职程序员可以很容易地使用它来组装诸如图像和插件之类的组件, 且代码是可以直接写在网页标记中. 除此之外微软的步步紧逼也迫使 Andreessen 不得不聘请 Brendan Eich, 及早将 Scheme 编程语言嵌入到 Netscape Navigator 中. 1995 年, JavaScript 以 Mocha 为名开发, 并于 9 月在 Netscape Navigator 2.0 的测试版中首次发布, 当时被称为 LiveScript,12 月, 在 Netscape Navigator 2.0 beta 3 中部署时被重命名为 JavaScript . 虽然 Netscape Navigator 在 Chrome,Internet Explorer 和 Firefox 等多款浏览器的围追堵截中最终落败, 但是 JavaScript 却推动了网页的发展, 并一直被沿用至今.
这是一个讽刺. 在 JavaScript 征服世界的同时, 播下了一颗很小的种子, 这可能会在将来的某个时候暗示 JavaScript 的终结. 那颗种子是名为 asm.JS 的实验技术.
这是 Mozilla 的开发人员在 2013 年完成的一个古怪的实验. 他们正在寻找在浏览器中运行高性能代码的方法. 但是与插件不同, asm.JS 并未尝试在浏览器旁边运行. 相反, 它的目的是直接通过 JavaScript 的虚拟化.
从本质上讲, asm.JS 是简洁, 优化的 JavaScript 语法. 它比普通的 JavaScript 运行得更快, 因为它避免了该语言的慢动态部分. 但是认识到它的网络浏览器也可以应用其他优化, 从而大大提高性能. 换句话说, asm.JS 遵循黄金法则 - 不要破坏网络 - 同时提供通往未来改进的途径. Firefox 团队使用 asm.JS 以及名为 https://en.wikipedia.org/wiki/Emscripten 的转码工具来获取用 C ++ 构建的实时 3D 游戏, 并将其放入 Web 浏览器中, 并且仅在 JavaScript 和原始野心上运行.
有人问为什么 asm.JS 好在哪里, 简单而言, 它的性能比 JavaScript 高几百倍, 当然是在没有谷歌的 V8 引擎之下, 因为 JavaScript 是若类型语言, 它需要猜测你的数据类型来进行编译, 这样的情况下, 在我看来它肯定需要遍历完一个方法, 然后再进行运算, 与其这样我为什么不打个标识呢? 当然在不破坏 JavaScript 的情况下, ARM.JS 选择了一个骚气的想法, 如果你想你的数据类型是 int, 那么声明一个值就变成了变量名 | 0, 就这样它的目的就达到了.
尽管 asm.JS 实验产生了一些令人眼花撩乱的演示, 但工作的开发人员基本上忽略了它. 对他们来说, 这只是超越现代的一个有趣方面. 但这随着 WebAssembly 的创建而改变.
WebAssembly 既是 asm.JS 的后继产品, 又是一项截然不同的技术. 这是一种紧凑的二进制代码格式. 像 asm.JS 一样, WebAssembly 代码也被输入到 JavaScript 执行环境中. 它具有相同的沙箱和相同的运行时环境. 与 asm.JS 一样, WebAssembly 的编译方式也可以提高效率. 但是现在, 这些效率比有以前更加明显, 并且浏览器可以完全跳过 JavaScript 解析阶段. 对于普通的逻辑, WebAssembly 远比常规 JavaScript 快, 几乎与本机编译的代码一样快.
WebAssembly 于 2015 年首次出现. 如今, 桌面和移动设备上的四大浏览器 (Chrome,Edge,Safari 和 Firefox) 已完全支持它. 尽管可以通过将 WebAssembly 代码转换为 asm.JS 来实现向后兼容, 但 Internet Explorer 不支持它. 就让 IE 凉透吧! 但需要注意的是 WebAssembly 无法回避 JavaScript, 因为它已锁定在 JavaScript 运行时环境中. 实际上, WebAssembly 需要与至少一些普通的 JavaScript 代码一起运行, 因为它不能直接访问页面. 这意味着如果不通过 JavaScript 层, 就无法操纵 DOM 或接收事件.
听我说起来, 这是一个限制, 但聪明的微软开发者已经找到了走私的方法, 在浏览器中下载一个微型. NET 运行时, 作为已编译的 WASM 文件. 此运行时处理 JavaScript 互操作, 并提供基本服务, 它能给我们提供 GC 或者其它用法. Blazor 不是唯一一个由 WebAssembly 支持的实验. 考虑一下 Pyodide, 它旨在将 Python 放入浏览器中, 并带有用于数据分析的高级数学工具包. 据我所知这应该使用 emscripten 的编译器.
人们常说, 何时 JavaScript 能够替代服务器端语言, 又有人说什么时候可以代替桌面级应用程序, 所以 WebAssembly 并不是用来代替 JavaScript 的. 而是为了解决现代问题, 如果它做到了, 那就真的做到了! 所以作为一个程序员, 你应该对 WebAssembly 引起足够的重视, 未来快速加载 Web 应用程序的需求肯定会增加.
就现在我们的. NET Core 提供了两种 Blazor 模板, 包括 Blazor Server 以及 Blazor WebAssembly.
Blazor Server 使用熟悉的. NET 环境在 Web 服务器上运行代码. 诀窍是浏览器和服务器之间的通信方式. 当用户与页面进行交互时, JavaScript 代码将回调到发生实际页面生命周期的服务器.(要建立此连接, 该页面使用名为 SignalR https://dotnet.microsoft.com/apps/aspnet/signalr 的 Microsoft API )运行服务器端代码后, Blazor Server 呈现该页面并将更改发送回 Web 页面, 该 Web 页面将相应地进行更新.
Blazor WebAssembly 使用由 WebAssembly 提供支持的微型. NET 运行时在浏览器中运行代码. 您的客户端代码可以访问许多熟悉的. NET 库, 并且您使用 C#语言编写它, 您仍然可以像在 JavaScript 页面中一样在 Web 服务器上调用 API.
Blazor Server 是一种具有一些有趣用例的技术, 但是由于不断的通信, 您显然会牺牲一些性能 - 甚至不用问脱机功能. Blazor WebAssembly 是受到最多宣传的一种, 也是我们在本文中探讨的一种.
关于 Blazor, 程序员最常见的误解是将其 C#代码编译为 WebAssembly, 然后发送到浏览器, 然后执行. 这种方法并非不可能 - Blazor 的创建者暗示他们将来可能会尝试这种技术. 但是如今 Blazor 的工作方式并不是如此.
换句话说, 如今的 Blazor 是当您访问使用 Blazor 的网页时, 该页面将从下载按比例缩小的. NET 运行时开始. 然后它将下载您的应用程序以及您的应用程序使用的任何其他. NET 库, 所有这些都在其本机 IL 中. 最后, Blazor 运行时执行 IL.
二. 配置您的开发环境
由于 Blazor 是一个预发布的早期 Beta 产品. 基础结构的关键部分正在发生变化, 您将无法获得与其他类型的 Microsoft 项目相同级别的工具支持. 我尝试在 Visual Studio 2019 中进行编码, 需要注意的是您需要勾选. NET FrameWork 4.8 以及 .NET Core 3.0 + , 这样您才具有 Web Assembly 的项目. 完成设置后, 您可以轻松创建 Blazor 项目. 只需启动 Visual Studio, 创建一个新项目, 然后选择 "Blazor App" 项目即可. Visual Studio 会询问您是否需要 Blazor Server 应用程序或 Blazor WebAssembly 应用程序.
三. Blazor 的数据绑定与组件传值
由于关于 Blazor 的. NET Core 又一杀器! Web Blazor 框架横空出世! 一篇我编写的文章, 未能提及更深入的内容, 那么现在我将要介绍一下高级的 Blazor 用法, 到最后还会有一个糖果, 园友力作的 Blazor UI! 多么激动人心的时刻, 那么赶快开始吧.
3.1Child Component
在 Blazor 的 Child Component 中可以使用[Parameter] 关键字, 来进行传值的定义, 我们可以这么来做, 现在只是提一下这个概念, 下面会仔细说下组件之间如何进行跨组件绑定值.
- <div>
- <p > 标题:@title</p>
- </div>
- @code{
- [Parameter]
- public string title { get; set; }
- }
随后在调用时, Visual Studio IDE 就可以直接向您的视觉进行提示输入相关属性.
<Demorazor title="Hello 博客园的兄弟们!"></Demorazor>
运行效果如下:
3.2 single Bind and Two-way binding
single bind 就不用说了, 新建项目自带的模板 Counter 示例那就是如此.
- @page "/counter"
- <h1>Counter</h1>
- <p>Current count: @currentCount</p>
- <button class="btn btn-primary" @onclick="IncrementCount">Click me</button>
- @code {
- private int currentCount = 0;
- private void IncrementCount()
- {
- currentCount++;
- }
- }
此处 @currentCount 值根据点击按钮的数量递增 Click me.<p > 标记元素中的值会自动刷新, 无需任何组件刷新.
two-way binding 我们可以自定义我们的事件 一共分为二中绑定方式 包括 @bind 和 @Bind-Value, 值得一提的是还可以通过使用 event 参数指定 @bind-value 属性, 使用其他事件来绑定属性或字段. 例如第四个文本框就是绑定 changeString 采用 oninput 事件的属性, 以到达在文本框的值更改时激发, 经过我的测试如果你的绑定事件是 JavaScript 中不存在的, 那么也无妨, 不会报出系统级别的异常, 我想如果是从 IL 转换到 WebAssembly 中, 就会直接过滤掉, 但是 Visual Studio 2019 没有给我们提示, 也让我们编译通过, 即使是当前的最高 16.0.4 预览版也是如此, 这个是令我诧异的.
- <p>
- <span > 在这里可以使用 bind-value 或者 bind 当然这里确保您不使用其它事件!</span>
- <input @bind-value="changeString" />
- <p > 这是我输入的内容: @changeString</p>
- </p>
- <p>
- <span>oninput</span>
- <input @bind-value="changeString" @bind-value:event="oninput" />
- </p>
- @code {
- string changeString = "";
- }
运行效果如下:
3.3 Component bindings
想要跨组件进行绑定属性值, 可以使用,@bind-{property}可在其中跨组件绑定属性值, 我们试着尝试, 首先我们创建一个子控件, 这个 blazor 就叫 Baby, 有一个身份证 Id 的属性和出生地址.
EventCallback 的用法非常广泛, 它可以跨组件共享方法和属性, 如不写下面的两个属性, 则就会报错.
- @page "/baby"
- <h2>Child Compoent</h2>
- <p > 出生的 Baby IdentityCard:@Baby_IdentityCrad_Id</p>
- <h3 > 在{@Baby_new_Address} 生的</h3>
- @code {
- [Parameter]
- public string Baby_IdentityCrad_Id{ get; set; }
- /// <summary>
- /// 这个属性也是牛的雅皮~~~ hhh
- /// </summary>
- [Parameter]
- public string Baby_new_Address{ get; set; }
- [Parameter]
- public EventCallback<string> Baby_IdentityCrad_IdChanged { get; set; }
- [Parameter]
- public EventCallback<string> Baby_new_AddressChanged { get; set; }
- }
有什么样的儿子就会有什么样的爸爸? 现在我们创建出父亲, 那就直接叫做一个 Father.razor 吧~
- @page "/father"
- <h3>Father</h3>
- <Baby @bind-Baby_IdentityCrad_Id="@id_Card"
- @bind-Baby_new_Address="@address">
- </Baby>
- <button class="btn btn-primary" @onclick="@ChangeTheYear">new baby()</button>
- @code {
- public string id_Card { get; set; }
- public string address { get; set; }
- private void ChangeTheYear()
- {
- id_Card = Guid.NewGuid().ToString();
- address = "老张";
- }
- }
运行效果如下:
如果要在子组件中定义事件, 则可以 MouseEventArgs 来接受设备上的事件, 然后再进行附加事件.
- [Parameter]
- public EventCallback<MouseEventArgs> OnClick {
- get; set;
- }
四. 级联传值
在某些情况下, 使用组件参数将数据从祖先组件流式传输到附属组件是不方便的, 尤其是在有多个组件层时. 级联值和参数通过提供一种方便的方法, 使上级组件为其所有子代组件提供值. 级联值和参数还提供了一种方法来协调组件. 我们试着去构建一个例子, 首先创建一个最顶层的组件.
- @page "/myDome"
- <p><span > 姓名:</span><input @bind="@pName" /></p>
- <p><span > 年龄:</span><input @bind-value="@pAge" @bind-value:event="oninput"/></p>
- <CascadingValue Value="@pName" Name="ProfileName">
- <CascadingValue Value="@pAge" Name="ProfileAge">
- <ParentComponent />
- </CascadingValue>
- </CascadingValue>
- @code {
- private string pName { get; set; } = "张三";
- private int pAge { get; set; } = 35;
- }
- ParentComponent.razor:
- <div style="background-color:darkgray;width:200px;">
- <p>Parent Component</p>
- <div style="padding:10px;">
- <p> 年龄 :@Age</p>
- <ChildComponent />
- </div>
- </div>
- @code{
- [CascadingParameter(Name = "ProfileAge")]
- int Age { get; set; }
- }
- ChildComponent.razor:
- <div style="background-color:beige;width:200px;">
- <p>Child Component</p>
- <p > 名称 : @Name.ToString()</p>
- </div>
- @code{
- [CascadingParameter(Name = "ProfileName")]
- string Name { get; set; }
- }
运行效果如下:
可以发现, 一级直接将二级和三级的组件进行了数据穿透, 不过需要注意的是 CascadingValue 的 Name 一定要和 CascadingParameter 的 Name 相同, 否则将会执行错误.
五. 路由
从古至今, 任何大型的开发框架, 都是具有路由的, 否则可能将会无法工作, 其实 Blazor 的启动页也就使用了路由, 这是毋庸置疑的. 当你的组件带有 @page 指令时, 将为生成的类指定 RouteAttribute 指定路由模板的. 在运行时, 路由器将使用 RouteAttribute 查找组件类, 并呈现哪个组件包含与请求的 URL 匹配的路由模板.
- @page "/luyou"
- @page "/luyou/{text}"
- <h1>Blazor is @Text!</h1>
- @code {
- [Parameter]
- public string Text { get; set; }
- protected override void OnInitialized()
- {
- Text = Text ?? "fantastic";
- }
- }
运行效果如下:
在上面的示例中应用了两个 @page 指令. 第一个允许导航到没有参数的组件. 第二个 @page 指令采用 {text} 路由参数, 并将该值分配给 Text 属性.
关于 Blazor 的基础入门咱们这篇就说到这里, 相信你一定觉得 Blazor 了不起! 它是一个现代的开源框架. 它也由一家拥有悠久历史的公司拥有, 该公司放弃了昨天的闪亮新技术. 因此, 大多数开发人员都应该谨慎对待 Blazor. 只要 JavaScript 能够执行 Blazor 可以做的所有事情, 而没有下载大小, 性能和新工具堆栈带来的额外挑战, 大多数开发人员将一如既往.
这并不意味着 Blazor 不能在所有这些领域都占有一席之地. 它甚至可能成为. NET Web 应用程序开发中的主导力量. 但是如果我今天必须下注, 这就是我要依靠的东西. WebAssembly 是未来. 但就目前而言, Blazor 只是一种有趣的可能性.
六. 彩蛋
就现在! 我的好朋友宇辰正在开发一款名为 Blazui 的 UI 组件. 它为什么叫 Blazui?
Blazor + Element UI = Blazui,Element UI 的 blazor 版本, 无 JS, 无 TS, 用 .Net 写前端的 UI 框架, 非 Silverlight, 非 WebForm, 开箱即用!!
Blazui 演示地址: http://blazui.com:9000/ .QQ 群: 74522853, 码云地址: https://gitee.com/wzxinchen/blazui
参考 Blazor 使用的前提条件:
安装 .Net Core 3.0
安装 VS2019
安装所有 VS2019 Blazor Extension
现在 Blazor 正在逐渐变好, 让我们即刻出发!.NET Core 不只是开源!
来源: https://www.cnblogs.com/ZaraNet/p/11924541.html