Blazor带我重玩前端(六)
本文主要討論Blazor事件內容,由于blazor事件部分很多,所以會分成上下兩篇,本文為第二篇。
雙向綁定
概述
如圖所示
當點擊單項綁定的時候,MyOnewayComponent里的屬性值會發生變化,這種變化是單項的,僅僅只是本地副本的值的變化,并不會引發父頁面的值發生變化。但當點擊父頁面的Click Me的時候,會修改MyOnewayComponent的屬性值會被修改。所以單項綁定強調的是占位,以達到動態輸出的目的。
當點擊雙向綁定的時候,三個值會同步發生變化。即便點擊父頁面的Click Me,也不會覆蓋掉MyTwoWayComponent的屬性值,這說明父頁面和MyTwoWayComponent頁面的值發生了雙向綁定,會導致數據同步變化。
雙向綁定,綁定的是Blazor組件和dom元素,就像是宏指令一樣。也就是說,當該組件首次運行時,輸入框的值來自于CurrentValue屬性,當用戶輸入新的值后,CurrentValue也將會被設置成新的值。
示例
雙向綁定有一個重要特征就是使用@bind-進行數據綁定,之前我創建了兩個組件,我們來看一下這兩個組件的源代碼:MyOnewayComponent:
<div>MyComponent CounterValue is @CounterValue </div> <button @onclick=UpdateCounterValue>Update</button> @code {[Parameter]public int CounterValue { get; set; }void UpdateCounterValue(){CounterValue++;} }MyTwoWayComponent:
<div>MyComponent CounterValue is @CounterValue </div> <button @onclick=UpdateCounterValue>Update</button> @code {[Parameter]public int CounterValue { get; set; }[Parameter]public EventCallback<int> CounterValueChanged { get; set; }async Task UpdateCounterValue(){CounterValue++;await CounterValueChanged.InvokeAsync(CounterValue);} }以上代碼可以看到有明顯的不同,MyTwoWayComponent包含一個EventCallback類型的屬性,其命名是CounterValueChanged,看起來像是屬性值后綴Changed,其調用方法也變成了async Task,該方法表明,當CounterValue發生變化的時候,會通過CounterValueChanged來通知事件源頁面該值發生了變化。額外嘗試一下,如果我們直接使用MyOnewayComponent 來演示雙向綁定,會發生什么,我們使用如下代碼運行一下看看:
<MyOnewayComponent @bind-CounterValue="@currentCount" />運行后,發現報錯了,錯誤信息是:Unhandled exception rendering component: Object of type 'BlazorApp.Client.Pages.MyOnewayComponent' does not have a property matching the name 'CounterValueChanged'。由此可見,我們的命名規則是強制的,其必須是所綁定EventCallBack的屬性名后綴Changed。
BuildTree源碼
#pragma warning disable 1998 protected override void BuildRenderTree(Microsoft.AspNetCore.Components.Rendering.RenderTreeBuilder __builder) {__builder.AddContent(8, "Click me");__builder.CloseElement();__builder.AddMarkupContent(9, "\r\n<br>\r\n<br>\r\n\r\n");__builder.OpenComponent<BlazorApp.Client.Pages.MyOnewayComponent>(10);__builder.AddAttribute(11, "CounterValue", Microsoft.AspNetCore.Components.CompilerServices.RuntimeHelpers.TypeCheck<System.Int32>( #nullable restorecurrentCount#line default #line hidden #nullable disable));__builder.AddAttribute(12, "CounterValueChanged", Microsoft.AspNetCore.Components.CompilerServices.RuntimeHelpers.CreateInferredEventCallback(this, __value => currentCount = __value, currentCount));__builder.CloseComponent(); }8-15行是單項綁定的內容
16-18行是雙向綁定的內容
級聯值和參數
概述
級聯值和參數是一種將值從組件傳遞到其所有子組件的方法,在Blazor中,采用CascadingValue來實現,子組件通過聲明同一類型的屬性(用[CascadingParameter]屬性修飾)來收集并賦值。當級聯值發生更新的時候,這種更新將傳遞到所有的子組件,同時這組件將會自動調用StateHasChanged 。一般情況下,我們的CascadingValue中可能會需要傳遞多個值的變化,那么這種變化是如何進行的呢。是通過兩種方式,一種是類型推導,一種是命名傳值。
類型推導
我創建了兩個組件,分別是FirstComponent,SecondComponent。FirstComponent源碼如下:
<CascadingValue Value="@CascadingIndex"><CascadingValue Value="@CascadingName"><SecondComponent></SecondComponent></CascadingValue> </CascadingValue> @code { int CascadingIndex = 10000;string CascadingName = "FirstComponent"; }SecondComponent源碼如下:
<h3>SecondComponent</h3> <p>CascadingValue Is <strong>@SecondValue</strong> </p> @code {[CascadingParameter] int SecondValue { get; set; } }傳值的過程中,我們只有一個int類型的屬性,所以該值會顯示10000,如下圖所示:如果我們修改一下FirstComponent的源碼,將其中的string類型的屬性刪除掉,同時增加一個新的int類型的屬性,如下源碼所示:運行結果如下:由此可見,當子組件遇到多個相同類型的屬性的時候,會選擇離子組件最近的屬性的值并傳遞到自己的屬性中去。
命名傳值
命名賦值就很單純了,主要考慮綁定正確的名稱就行。修改后FirstComponent的源碼如下,需要指定Name
<CascadingValue Value="@CascadingIndex" Name="CascadingIndex"><CascadingValue Value="@Total" Name="Total"><SecondComponent></SecondComponent></CascadingValue> </CascadingValue>@code {int CascadingIndex{ get; set; } = 10000;int Total{ get; set; } = 2; }SecondComponent源碼如下,可以指定名稱已接收值的傳遞
<h3>SecondComponent</h3> <p>CascadingValue Is <strong>@SecondValue</strong> </p> @code {[CascadingParameter(Name = "CascadingIndex")] int SecondValue { get; set; } }運行后的結果如下,值又變回了10000,有朋友可能會想,我不想設置SecondComponent中CascadingParameter的Name值,但是我可以設置成FirstComponent中某個已經綁定的Name的名稱。如下所示:FirstComponent源碼不變,SecondComponent源碼如下:
<h3>SecondComponent</h3> <p>CascadingValue Is <strong>@Total</strong> </p> @code {[CascadingParameter] int Total { get; set; } }運行結果如下所示:由此可見,不設置子組件中CascadingParameter的Name值,是無法接收傳遞的值的。
性能問題
默認情況下,Blazor會持續監控級聯值的變化,并將其傳遞到所有子組件中,這將會占用一定的資源,并可能導致性能問題。如果我們可以確定,我們的級聯值不會發生變化,可以設置CascadingValue中參數IsFixed的值為true,這樣的Blazor就不會監控級聯值的變化了。
<CascadingValue Value="@CascadingIndex" IsFixed="true"><SecondComponent></SecondComponent> </CascadingValue>總結
以上是生活随笔為你收集整理的Blazor带我重玩前端(六)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 使用 C# 捕获进程输出
- 下一篇: 深入探究.Net Core Config