經過Blazor使用C#開發SPA單頁面應用程序(1) - 簡介及特色html
經過Blazor使用C#開發SPA單頁面應用程序(2) - 開發環境瀏覽器
經過Blazor使用C#開發SPA單頁面應用程序(3) - 基礎知識框架
經過Blazor使用C#開發SPA單頁面應用程序(4) - Ant Design Button異步
今天咱們來看看Blazor開發的一些基本知識。函數
Blazor中組件的基本結構能夠分爲3個部分,以下所示:學習
//Counter.razor
//Directives section 指令部分 @page "/counter" //Razor HTML section Razor HTML部分 <h1>Counter</h1> <p>Current count: @currentCount</p> <button class="btn btn-primary" onclick="@IncrementCount">Click me</button> //code sections 功能部分 @code { private int currentCount = 0; private void IncrementCount() { currentCount++; } }
Razor HTML語法是C#代碼與HTML的結合。此部分最終在瀏覽器中呈現。spa
組件中的函數部分包含用戶操做函數(事件方法),局部變量和從/向父/子組件傳遞的屬性。3d
固然若是願意,這部分也能夠單獨寫道類文件中。雙向綁定
咱們看看屬性和參數,code
<button id="btnClickMe" class="btn btn-primary" onclick="@IncrementCount">Click me</button>
在這裏,在按鈕元素的id,class和onclick被稱爲HTML屬性。
相似地,組件的定義方式與HTML元素相同,
@page "/myDome" <h3>MyDemo</h3> <ChildComponent Title="來自MyDemo"></ChildComponent>
在Child Component中,該屬性Title與裝飾的子組件函數部分中的屬性匹配 [Parameter] 關鍵字。
//ChildComponent.razor
//Child Component <div> <p>標題 : @Title</p> </div> @code { [Parameter] private string Title { get; set; } }
運行效果以下:
Blazor的數據綁定同時提供了單向綁定和雙向綁定兩種機制。
單向綁定在Blazor中簡單直接,無需任何UI刷新。還記得Counter示例嗎,他顯示了單向數據綁定,
@page "/counter" <h1>Counter</h1> <p>Current count: @currentCount</p> <button class="btn btn-primary" @onclick="@IncrementCount">Click me</button> @code { int currentCount = 0; void IncrementCount() { currentCount++; } }
此處 @currentCount 值根據點擊按鈕的數量遞增Click me。<p>標記元素中的值會自動刷新,無需任何組件刷新。
在Blazor中能夠實現雙向綁定,與一些流行的JS語言框架相比,Blazor爲雙向綁定提供了多種實現方式,Blazor能夠優雅地進行編寫。
(1) @bind屬性在Blazor中提供雙向數據綁定。下面的示例複選框演示在同一組件中的bind屬性,
@page "/myDome" <span>請選擇:</span> <input type="checkbox" @bind="myChecked" /> <p>我選擇了 : @myChecked.ToString()</p> @code { bool myChecked { get; set; } = true; }
運行效果以下,是否是很簡單,很優雅。
再來一個控制樣式表的例子看看,
@page "/myDome" <p> <span>顯示/隱藏:</span> <input type="checkbox" @bind="myChecked" /> </p> <p style="display:@(myChecked ? "inline":"none")">看到我了</p> @code { bool myChecked { get; set; } = true; }
(2) @bind屬性在Blazor中提供雙向數據綁定,可是隻提供了默認的綁定事件,若是們想在不一樣的時機觸發雙向綁定該怎麼辦呢,別急一樣很簡單的,咱們看看下面的代碼,展現了幾種綁定實例,
@page "/myDome" <p> <span>onchange 方式一</span> <input @bind="changeString" /> </p> <p> <span>onchange 方式二</span> <input type="text" value="@changeString" @onchange="@((UIChangeEventArgs _e) => changeString = _e.Value.ToString())" /> </p> <p> <span>onchange 方式三</span> <input @bind-value="changeString" @bind-value:event="onchange" /> </p> <p> <span>oninput</span> <input @bind-value="changeString" @bind-value:event="oninput" /> </p> <p>這是我輸入的內容: @changeString</p> @code { string changeString = ""; }
運行效果以下,
呈現組件時, input元素value的值來自changeString。 當用戶在文本框中鍵入內容並離開時, 將觸發事件onchange更改changeString的值。原則上, @bind將表達式的當前值value與changeString相關聯, 並使用註冊的處理程序來處理更改。
除了使用@bind語法處理onchange事件以外, 還能夠經過使用event參數 (@bind-value:event) 指定@bind-value屬性, 使用其餘事件來綁定屬性或字段。例如第四個文本框就是綁定changeString採用oninput事件的屬性,以到達在文本框的值更改時激發。
(三)組件之間綁定:
(1)綁定可識別組件參數, @bind-{property}可在其中跨組件綁定屬性值。
//MyDemo.razor @page "/myDome" <h1>Parent Component</h1> <p>當前時間: @ParentNow</p> <hr /> <ChildComponent @bind-Now="ParentNow" /> <hr /> <button class="btn btn-primary" @onclick="@ChangeTheYear"> 更新當前時間 </button> @code { [Parameter] public DateTime ParentNow { get; set; } = DateTime.Now; private void ChangeTheYear() { ParentNow = DateTime.Now; } }
//ChildComponent.razor <h2>Child Component</h2> <p>當前時間: @Now</p> @code { [Parameter] public DateTime Now { get; set; } [Parameter] public EventCallback<DateTime> NowChanged { get; set; } }
以上代碼中,子組件 (ChildComponent) 具備一個Now組件參數和NowChanged回調參數,父組件MyDemo使用ChildComponent
並將ParentNow
參數從父級綁定到子組件上Now
的參數上,若是經過點擊MyDemo
中的"更新當前時間"
按鈕來更改屬性的值, Now
則將更新ChildComponent
屬性,將新值呈如今 UI中。其中,參數Now是可綁定的, 由於它具備NowChanged與參數類型匹配的伴隨事件。按照約定,其等效於
<ChildComponent @bind-Now="ParentNow" @bind-Now:event="NowChanged" />
運行效果:
(2)組件之間傳遞的數據經過組件屬性及其屬性映射發生,此方法使用委託Action<T>類型。
//MyDemo.razor @page "/myDome" <h3>Parent Component</h3> <p>來自Child組件: @childString</p> <p> <input @bind="inputText" /> </p> <hr /> <ChildComponent ToChild="@inputText" FromChild="@ReceivedFromChild"> </ChildComponent> @code{ private string inputText = ""; private string childString = ""; private void ReceivedFromChild(string str) { childString = str; StateHasChanged(); } }
//ChildComponent.razor <h4>Child Component</h4> <p> <input @bind="inputText" /> <button @onclick="@PassToParent">顯示到Parent組件</button> </p> <p>來自Parent組件 : @ToChild</p> @code{ [Parameter] private string ToChild { get; set; } [Parameter] Action<string> FromChild { get; set; } private string inputText = ""; private void PassToParent() { FromChild(inputText); } }
這裏FromChild是ChildComponent中的屬性,屬性使用Action<string>數據類型將值從Child傳遞給Parent Component。在Parent中,有相應的接收器函數ReceivedFromChild和字符串參數,這將在ChildComponent中按鈕單擊並觸發通知時觸發PassToParent,可是爲了通知狀態已在父組件中更改,咱們使用StateHasChanged()的內置Blazor函數通知組件其狀態已更改。
運行效果以下:
(1) OnInitializedAsync和OnInitialized方法,執行代碼來初始化組件。要執行異步操做,請在操做上使用OnInitializedAsync和await關鍵字。
(2)OnParametersSetAsync和OnParametersSet當組件已接收到的參數從其父和值被分配給屬性被調用。這些方法在組件初始化後以及每次呈現組件時執行。
(3)OnAfterRenderAsync並OnAfterRender在組件完成渲染後調用。此時填充元素和組件引用。使用此階段使用呈現的內容執行其餘初始化步驟,例如激活對呈現的DOM元素進行操做的第三方JavaScript庫。
在某些狀況下, 使用組件參數將數據從祖先組件流式傳輸到附屬組件是不方便的, 尤爲是在有多個組件層時。 級聯值和參數經過提供一種方便的方法, 使上級組件爲其全部子代組件提供值。 級聯值和參數還提供了一種方法來協調組件。
Blazor提供了一種在整個RenderTree(全部組件)中傳遞數據的方法,使用CascadingValue和CascadingParameter不須要傳遞做爲組件屬性,而且能夠經過裝飾屬性[CascadingParameter]而不用在RenderTree(子組件)中接收值[Parameter]。
//MyDemo.razor @page "/myDome" <p><span>姓名:</span><input @bind="@pName" /></p> <p><span>年齡:</span><input @bind="@pAge" /></p> <hr /> <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"> <p>Parent Component</p> <div style="padding:10px;"> <ChildComponent /> </div> </div>
//ChildComponent.razor <div style="background-color:beige"> <p>Child Component</p> <p>輸入的 姓名: @Name , 年齡 : @Age.ToString()</p> </div> @code{ [CascadingParameter(Name = "ProfileName")] string Name { get; set; } [CascadingParameter(Name = "ProfileAge")] int Age { get; set; } }
代碼中MyDemo的姓名、年齡穿透ParentComponent直接級聯到ChildComponent中。
在這裏CascadingParameter,Name參數必須與Name帶有CascadingValue組件的屬性匹配,若是咱們沒有提到任何Name,則CascadingParameter中的變量類型與CascadingValue中的Value屬性匹配。
運行效果:
咱們在看一個SPA中一個基本但很重要的功能路由。客戶端路由能夠經過使用@page指令裝飾組件來在Blazor中完成。
@page "/myDome" @page "/myDome/{text}"
@page在上面的示例中應用了兩個指令。
第一個容許在沒有參數的狀況下導航到組件。
第二個@page指令採用{text}route參數並將值賦給Text屬性。
好了今天Blazor的組件開發就先學習到這,有意猶未盡的能夠查看官方文檔深刻學習。