.NET开发者的机遇与Web Blazor基础(有彩蛋)
一.嘮嘮WebAssembly的發(fā)展歷程
目前有很多支持WebAssembly的項(xiàng)目,但發(fā)展最快的是Blazor,這是一個(gè)構(gòu)建單頁(yè)面的.NET技術(shù),目前已經(jīng)從Preview版本升級(jí)到了beta版本,微軟計(jì)劃在2020年5月發(fā)布Blazor的第一個(gè)版本。
Blazor是什么?它是一項(xiàng)將C#和.NET都放入瀏覽器的Microsoft技術(shù)。它使用WebAssembly來(lái)工作,WebAssembly是一種高性能的管道,可以將代碼預(yù)編譯為緊湊的二進(jìn)制格式。最重要的是,每個(gè)主流瀏覽器(包括移動(dòng)版本)都支持WebAssembly。
十年前,JavaScript統(tǒng)治世界還不是很明顯。Flash和Silverlight也正在運(yùn)行。這二個(gè)都需要使用瀏覽器插件來(lái)完成工作,并且都以不同的用戶界面方法替換了HTML。這種方法使他們?cè)诠δ芊矫孢b遙領(lǐng)先于JavaScript,但隨著移動(dòng)互聯(lián)網(wǎng)的出現(xiàn),他們就慢慢過(guò)時(shí)。
但隨后從最初的Javascript再到微軟的JScript和CEnvi的ScriptEase三足鼎立,再到最后的統(tǒng)一標(biāo)準(zhǔn),當(dāng)時(shí)微軟憑借Windows系統(tǒng)捆綁Internet Explorer的先天優(yōu)勢(shì)擊潰Netscape后,兩大巨頭就此進(jìn)入了長(zhǎng)達(dá)數(shù)年的靜默期,JavaScript就是在這樣的情況下被構(gòu)想出來(lái)的,當(dāng)時(shí)的瀏覽器之王,Netscape Navigator創(chuàng)始人Marc Andreessen認(rèn)為Netscape需要一種“glue language”來(lái)支持HTML,讓W(xué)eb設(shè)計(jì)師和兼職程序員可以很容易地使用它來(lái)組裝諸如圖像和插件之類的組件,且代碼是可以直接寫在網(wǎng)頁(yè)標(biāo)記中。除此之外微軟的步步緊逼也迫使Andreessen不得不聘請(qǐng)Brendan Eich,及早將Scheme編程語(yǔ)言嵌入到Netscape Navigator中。1995年,JavaScript以Mocha為名開(kāi)發(fā),并于9月在Netscape Navigator 2.0的測(cè)試版中首次發(fā)布,當(dāng)時(shí)被稱為L(zhǎng)iveScript,12月,在Netscape Navigator 2.0 beta 3中部署時(shí)被重命名為JavaScript 。雖然Netscape Navigator在Chrome、Internet Explorer和Firefox等多款瀏覽器的圍追堵截中最終落敗,但是JavaScript卻推動(dòng)了網(wǎng)頁(yè)的發(fā)展,并一直被沿用至今。
這是一個(gè)諷刺。在JavaScript征服世界的同時(shí),播下了一顆很小的種子,這可能會(huì)在將來(lái)的某個(gè)時(shí)候暗示JavaScript的終結(jié)。那顆種子是名為asm.js的實(shí)驗(yàn)技術(shù)。
這是Mozilla的開(kāi)發(fā)人員在2013年完成的一個(gè)古怪的實(shí)驗(yàn)。他們正在尋找在瀏覽器中運(yùn)行高性能代碼的方法。但是與插件不同,asm.js并未嘗試在瀏覽器旁邊運(yùn)行。相反,它的目的是直接通過(guò)Javascript的虛擬化。
從本質(zhì)上講,asm.js是簡(jiǎn)潔,優(yōu)化的JavaScript語(yǔ)法。它比普通的JavaScript運(yùn)行得更快,因?yàn)樗苊饬嗽撜Z(yǔ)言的慢動(dòng)態(tài)部分。但是認(rèn)識(shí)到它的網(wǎng)絡(luò)瀏覽器也可以應(yīng)用其他優(yōu)化,從而大大提高性能。換句話說(shuō),asm.js遵循黃金法則-?不要破壞網(wǎng)絡(luò)?-同時(shí)提供通往未來(lái)改進(jìn)的途徑。Firefox團(tuán)隊(duì)使用asm.js以及名為Emscripten的轉(zhuǎn)碼工具來(lái)獲取用C ++構(gòu)建的實(shí)時(shí)3D游戲,并將其放入Web瀏覽器中,并且僅在JavaScript和原始野心上運(yùn)行。
有人問(wèn)為什么asm.js好在哪里,簡(jiǎn)單而言,它的性能比JavaScript高幾百倍,當(dāng)然是在沒(méi)有谷歌的V8引擎之下,因?yàn)镴avaScript是若類型語(yǔ)言,它需要猜測(cè)你的數(shù)據(jù)類型來(lái)進(jìn)行編譯,這樣的情況下,在我看來(lái)它肯定需要遍歷完一個(gè)方法,然后再進(jìn)行運(yùn)算,與其這樣我為什么不打個(gè)標(biāo)識(shí)呢?當(dāng)然在不破壞JavaScript的情況下,arm.js選擇了一個(gè)騷氣的想法,如果你想你的數(shù)據(jù)類型是int,那么聲明一個(gè)值就變成了變量名|0,就這樣它的目的就達(dá)到了。
盡管asm.js實(shí)驗(yàn)產(chǎn)生了一些令人眼花撩亂的演示,但工作的開(kāi)發(fā)人員基本上忽略了它。對(duì)他們來(lái)說(shuō),這只是超越現(xiàn)代的一個(gè)有趣方面。但這隨著WebAssembly的創(chuàng)建而改變。
WebAssembly既是asm.js的后繼產(chǎn)品,又是一項(xiàng)截然不同的技術(shù)。這是一種緊湊的二進(jìn)制代碼格式。像asm.js一樣,WebAssembly代碼也被輸入到JavaScript執(zhí)行環(huán)境中。它具有相同的沙箱和相同的運(yùn)行時(shí)環(huán)境。與asm.js一樣,WebAssembly的編譯方式也可以提高效率。但是現(xiàn)在,這些效率比有以前更加明顯,并且瀏覽器可以完全跳過(guò)JavaScript解析階段。對(duì)于普通的邏輯,WebAssembly遠(yuǎn)比常規(guī)JavaScript快,幾乎與本機(jī)編譯的代碼一樣快。
? WebAssembly于2015年首次出現(xiàn)。如今,桌面和移動(dòng)設(shè)備上的四大瀏覽器(Chrome,Edge,Safari和Firefox)已完全支持它。盡管可以通過(guò)將WebAssembly代碼轉(zhuǎn)換為asm.js來(lái)實(shí)現(xiàn)向后兼容,但I(xiàn)nternet Explorer不支持它。就讓IE涼透吧!但需要注意的是WebAssembly無(wú)法回避JavaScript,因?yàn)樗焰i定在JavaScript運(yùn)行時(shí)環(huán)境中。實(shí)際上,WebAssembly需要與至少一些普通的JavaScript代碼一起運(yùn)行,因?yàn)樗荒苤苯釉L問(wèn)頁(yè)面。這意味著如果不通過(guò)JavaScript層,就無(wú)法操縱DOM或接收事件。
? 聽(tīng)我說(shuō)起來(lái),這是一個(gè)限制,但聰明的微軟開(kāi)發(fā)者已經(jīng)找到了走私的方法,在瀏覽器中下載一個(gè)微型.NET運(yùn)行時(shí),作為已編譯的WASM文件。此運(yùn)行時(shí)處理JavaScript互操作,并提供基本服務(wù),它能給我們提供GC或者其它用法。Blazor不是唯一一個(gè)由WebAssembly支持的實(shí)驗(yàn)。考慮一下Pyodide,它旨在將Python放入瀏覽器中,并帶有用于數(shù)據(jù)分析的高級(jí)數(shù)學(xué)工具包。據(jù)我所知這應(yīng)該使用emscripten的編譯器。
? 人們常說(shuō),何時(shí)Javascript能夠替代服務(wù)器端語(yǔ)言,又有人說(shuō)什么時(shí)候可以代替桌面級(jí)應(yīng)用程序,所以WebAssembly并不是用來(lái)代替JavaScript的。而是為了解決現(xiàn)代問(wèn)題,如果它做到了,那就真的做到了!所以作為一個(gè)程序員,你應(yīng)該對(duì)WebAssembly引起足夠的重視,未來(lái)快速加載Web應(yīng)用程序的需求肯定會(huì)增加。
? 就現(xiàn)在我們的.NET Core提供了兩種Blazor模板,包括Blazor Server 以及 Blazor WebAssembly。
- Blazor Server使用熟悉的.NET環(huán)境在Web服務(wù)器上運(yùn)行代碼。訣竅是瀏覽器和服務(wù)器之間的通信方式。當(dāng)用戶與頁(yè)面進(jìn)行交互時(shí),JavaScript代碼將回調(diào)到發(fā)生實(shí)際頁(yè)面生命周期的服務(wù)器。(要建立此連接,該頁(yè)面使用名為SignalR的Microsoft API )運(yùn)行服務(wù)器端代碼后,Blazor Server呈現(xiàn)該頁(yè)面并將更改發(fā)送回Web頁(yè)面,該Web頁(yè)面將相應(yīng)地進(jìn)行更新。 
- Blazor WebAssembly使用由WebAssembly提供支持的微型.NET運(yùn)行時(shí)在瀏覽器中運(yùn)行代碼。您的客戶端代碼可以訪問(wèn)許多熟悉的.NET庫(kù),并且您使用C#語(yǔ)言編寫它,您仍然可以像在JavaScript頁(yè)面中一樣在Web服務(wù)器上調(diào)用API。 
Blazor Server是一種具有一些有趣用例的技術(shù),但是由于不斷的通信,您顯然會(huì)犧牲一些性能-甚至不用問(wèn)脫機(jī)功能。Blazor WebAssembly是受到最多宣傳的一種,也是我們?cè)诒疚闹刑接懙囊环N。
關(guān)于Blazor,程序員最常見(jiàn)的誤解是將其C#代碼編譯為WebAssembly,然后發(fā)送到瀏覽器,然后執(zhí)行。這種方法并非不可能-Blazor的創(chuàng)建者暗示他們將來(lái)可能會(huì)嘗試這種技術(shù)。但是如今Blazor的工作方式并不是如此。
換句話說(shuō),如今的Blazor是當(dāng)您訪問(wèn)使用Blazor的網(wǎng)頁(yè)時(shí),該頁(yè)面將從下載按比例縮小的.NET運(yùn)行時(shí)開(kāi)始。然后它將下載您的應(yīng)用程序以及您的應(yīng)用程序使用的任何其他.NET庫(kù),所有這些都在其本機(jī)IL中。最后,Blazor運(yùn)行時(shí)執(zhí)行IL。
二.配置您的開(kāi)發(fā)環(huán)境
? 由于Blazor是一個(gè)預(yù)發(fā)布的早期Beta產(chǎn)品。基礎(chǔ)結(jié)構(gòu)的關(guān)鍵部分正在發(fā)生變化,您將無(wú)法獲得與其他類型的Microsoft項(xiàng)目相同級(jí)別的工具支持。我嘗試在Visual Studio 2019中進(jìn)行編碼,需要注意的是您需要勾選.NET FrameWork 4.8 以及 .NET Core 3.0 + ,這樣您才具有Web Assembly的項(xiàng)目。完成設(shè)置后,您可以輕松創(chuàng)建Blazor項(xiàng)目。只需啟動(dòng)Visual Studio,創(chuàng)建一個(gè)新項(xiàng)目,然后選擇“ Blazor App”項(xiàng)目即可。Visual Studio會(huì)詢問(wèn)您是否需要Blazor Server應(yīng)用程序或Blazor WebAssembly應(yīng)用程序.
?三.Blazor的數(shù)據(jù)綁定與組件傳值
由于關(guān)于Blazor的.NET Core 又一殺器! Web Blazor框架橫空出世!一篇我編寫的文章,未能提及更深入的內(nèi)容,那么現(xiàn)在我將要介紹一下高級(jí)的Blazor用法,到最后還會(huì)有一個(gè)糖果,園友力作的Blazor UI!多么激動(dòng)人心的時(shí)刻,那么趕快開(kāi)始吧.
3.1Child Component
在Blazor的Child Component中可以使用[Parameter] 關(guān)鍵字,來(lái)進(jìn)行傳值的定義,我們可以這么來(lái)做,現(xiàn)在只是提一下這個(gè)概念,下面會(huì)仔細(xì)說(shuō)下組件之間如何進(jìn)行跨組件綁定值。
<div><p>標(biāo)題:@title</p>
</div>
@code{
[Parameter]
public string title { get; set; }
}
隨后在調(diào)用時(shí),Visual Studio IDE 就可以直接向您的視覺(jué)進(jìn)行提示輸入相關(guān)屬性。
<Demorazor title="Hello 博客園的兄弟們!"></Demorazor>運(yùn)行效果如下:
3.2 single Bind and Two-way binding
single bind就不用說(shuō)了,新建項(xiàng)目自帶的模板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 值根據(jù)點(diǎn)擊按鈕的數(shù)量遞增Click me。<p>標(biāo)記元素中的值會(huì)自動(dòng)刷新,無(wú)需任何組件刷新。
two-way binding 我們可以自定義我們的事件 一共分為二中綁定方式 包括@bind 和 @Bind-Value,值得一提的是還可以通過(guò)使用event參數(shù)指定@bind-value屬性, 使用其他事件來(lái)綁定屬性或字段。例如第四個(gè)文本框就是綁定changeString采用oninput事件的屬性,以到達(dá)在文本框的值更改時(shí)激發(fā),經(jīng)過(guò)我的測(cè)試如果你的綁定事件是Javascript中不存在的,那么也無(wú)妨,不會(huì)報(bào)出系統(tǒng)級(jí)別的異常,我想如果是從IL轉(zhuǎn)換到WebAssembly中,就會(huì)直接過(guò)濾掉,但是Visual Studio 2019 沒(méi)有給我們提示,也讓我們編譯通過(guò),即使是當(dāng)前的最高16.0.4 預(yù)覽版也是如此,這個(gè)是令我詫異的。
<p><span>在這里可以使用bind-value 或者 bind 當(dāng)然這里確保您不使用其它事件!</span>
<input @bind-value="changeString" />
<p>這是我輸入的內(nèi)容: @changeString</p>
</p>
<p>
<span>oninput</span>
<input @bind-value="changeString" @bind-value:event="oninput" />
</p>
@code {
string changeString = "";
}
運(yùn)行效果如下:
?3.3?Component bindings
? 想要跨組件進(jìn)行綁定屬性值,可以使用,@bind-{property}可在其中跨組件綁定屬性值,我們?cè)囍鴩L試,首先我們創(chuàng)建一個(gè)子控件,這個(gè)blazor就叫Baby,有一個(gè)身份證Id的屬性和出生地址。
EventCallback的用法非常廣泛,它可以跨組件共享方法和屬性,如不寫下面的兩個(gè)屬性,則就會(huì)報(bào)錯(cuò)。
@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>
/// 這個(gè)屬性也是牛的雅皮~~~ 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; }
}
? 有什么樣的兒子就會(huì)有什么樣的爸爸?現(xiàn)在我們創(chuàng)建出父親,那就直接叫做一個(gè)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 = "老張";
}
}
運(yùn)行效果如下:
?
?如果要在子組件中定義事件,則可以MouseEventArgs來(lái)接受設(shè)備上的事件,然后再進(jìn)行附加事件。
[Parameter]public EventCallback<MouseEventArgs> OnClick { get; set; }
四.級(jí)聯(lián)傳值
? 在某些情況下, 使用組件參數(shù)將數(shù)據(jù)從祖先組件流式傳輸?shù)礁綄俳M件是不方便的, 尤其是在有多個(gè)組件層時(shí)。級(jí)聯(lián)值和參數(shù)通過(guò)提供一種方便的方法, 使上級(jí)組件為其所有子代組件提供值。級(jí)聯(lián)值和參數(shù)還提供了一種方法來(lái)協(xié)調(diào)組件。我們?cè)囍?gòu)建一個(gè)例子,首先創(chuàng)建一個(gè)最頂層的組件。
@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; }
}
?運(yùn)行效果如下:
?
?可以發(fā)現(xiàn),一級(jí)直接將二級(jí)和三級(jí)的組件進(jìn)行了數(shù)據(jù)穿透,不過(guò)需要注意的是CascadingValue的Name一定要和CascadingParameter的Name相同,否則將會(huì)執(zhí)行錯(cuò)誤。
五.路由
? 從古至今,任何大型的開(kāi)發(fā)框架,都是具有路由的,否則可能將會(huì)無(wú)法工作,其實(shí)Blazor的啟動(dòng)頁(yè)也就使用了路由,這是毋庸置疑的。當(dāng)你的組件帶有?@page?指令時(shí),將為生成的類指定 RouteAttribute 指定路由模板的。?在運(yùn)行時(shí),路由器將使用?RouteAttribute?查找組件類,并呈現(xiàn)哪個(gè)組件包含與請(qǐng)求的 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";
}
}
運(yùn)行效果如下:
在上面的示例中應(yīng)用了兩個(gè)?@page?指令。?第一個(gè)允許導(dǎo)航到?jīng)]有參數(shù)的組件。?第二個(gè)?@page?指令采用?{text}?路由參數(shù),并將該值分配給?Text?屬性。
關(guān)于Blazor的基礎(chǔ)入門咱們這篇就說(shuō)到這里,相信你一定覺(jué)得Blazor了不起!它是一個(gè)現(xiàn)代的開(kāi)源框架。它也由一家擁有悠久歷史的公司擁有,該公司放棄了昨天的閃亮新技術(shù)。因此,大多數(shù)開(kāi)發(fā)人員都應(yīng)該謹(jǐn)慎對(duì)待Blazor。只要JavaScript能夠執(zhí)行Blazor可以做的所有事情,而沒(méi)有下載大小,性能和新工具堆棧帶來(lái)的額外挑戰(zhàn),大多數(shù)開(kāi)發(fā)人員將一如既往。
這并不意味著B(niǎo)lazor不能在所有這些領(lǐng)域都占有一席之地。它甚至可能成為.NET Web應(yīng)用程序開(kāi)發(fā)中的主導(dǎo)力量。但是如果我今天必須下注,這就是我要依靠的東西。WebAssembly是未來(lái)。但就目前而言,Blazor只是一種有趣的可能性。
六.彩蛋
就現(xiàn)在!我的好朋友宇辰正在開(kāi)發(fā)一款名為Blazui的UI組件。它為什么叫Blazui?
Blazor + Element UI = Blazui,Element UI 的blazor版本,無(wú)JS,無(wú)TS,用 .Net 寫前端的 UI 框架,非 Silverlight,非 WebForm,開(kāi)箱即用!!
Blazui 演示地址:http://blazui.com:9000。QQ群:74522853,碼云地址:https://gitee.com/wzxinchen/blazui
參考Blazor使用的前提條件:
安裝 .Net Core 3.0
安裝 VS2019
安裝所有 VS2019 Blazor Extension
現(xiàn)在Blazor正在逐漸變好,讓我們即刻出發(fā)!.NET Core 不只是開(kāi)源!
出處:
https://www.cnblogs.com/ZaraNet/archive/2019/11/24/11924541.html
總結(jié)
以上是生活随笔為你收集整理的.NET开发者的机遇与Web Blazor基础(有彩蛋)的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
 
                            
                        - 上一篇: .NET core3.0 使用Jwt保护
- 下一篇: 容器日志管理 (2) 开源日志管理方案
