【Blazor】|?總結/Edison Zhou
大家好,我是Edison。前幾天沒有發布本篇就發布了第五篇,屬于操作失誤哈,這次把第四篇補上!
本篇,我們來了解下在Blazor中數據是如何共享的,組件之間又該如何傳遞參數。
關于Blazor組件在 Blazor 中,從名為“組件”的自包含代碼部分生成 UI。每個組件都可以包含 HTML 和 C# 代碼的混合。組件是通過使用 Razor 語法編寫的,其中的代碼是用?@code 指令標記的。其他指令可用于訪問變量、綁定到值以及實現其他呈現任務。
編譯應用時,HTML 和代碼將編譯為組件類。組件一般被編寫為擴展名為 .razor 的文件。
關于數據共享
Blazor 包含多種在組件之間共享信息的方法。
(1)可使用組件參數或級聯參數將值從父組件發送到子組件。
(2)AppState 模式是另一種可用于存儲值并從應用程序中的任何組件訪問這些值的方法。
使用組件參數共享
在父組件和子組件的此層次結構中,可以使用組件參數在它們之間共享信息。在子組件上定義這些參數,然后在父組件中設置其值。
例如,在Counter組件中,定義了一個IncrementAmount的組件參數:
@page "/counter"<PageTitle>Counter</PageTitle><h1>Counter</h1><p role="status">Current count: @currentCount</p><button class="btn btn-primary" @onclick="IncrementCount">Click me</button>@code {private int currentCount = 0;[Parameter]public int IncrementAmount { get; set; } = 1;private void IncrementCount(){currentCount += IncrementAmount;}
}
在調用端只需要下面這樣既可,由于Counter組件中還設置了默認值為1,因此,如果調用端不傳遞,則默認為1。
<Counter IncrementAmount="10" />
此外,還可以使用自定義類用作組件參數,例如:
@using EDT.BlazorServer.App.Models<p>New Topping: @Topping.Name</p>
<p>Ingredients: @Topping.Ingredients</p>@code {[Parameter]public PizzaTopping Topping { get; set; }
}
PizzaTopping的定義如下:
public class PizzaTopping
{public string Name { get; set; }public string Ingredients { get; set; }
}
調用方的定義如下:
@page "/pizzas-toppings"<h1>Our Latest Pizzas and Topping</h1><PizzaTopping Topping="@(new PizzaTopping() { Name = "Chilli Sauce", Ingredients = "Three kinds of chilli." })" />
使用級聯參數共享
當具有包含子組件的子組件的較深層次結構時,事情便會變得難以應付。組件參數不會從上級組件或沿著層次結構向下自動傳遞到下級組件。為了完美處理此問題,Blazor 包含了級聯參數。在組件中設置級聯參數的值時,其值將自動提供給所有子組件。
在父組件中,使用??標記指定將級聯到所有子組件的信息。此標記作為內置的 Blazor 組件實現。在該標記內呈現的任何組件都將能夠訪問該值。
例如,我們有三個組件,其中,CascComp2組件被嵌套在CascComp1組件中,而CascComp1組件又被嵌套在CascCompSamle組件中。他們的調用關系如下:
使用CascadingParameter級聯傳遞參數NickName:
(1)CascCompSample.razor
<!--this is CascCompSample.razor-->@page "/cascparamsample"<h3>This is the sample page</h3><CascadingValue Value="NickName"><CascComp1></CascComp1>
</CascadingValue>@code
{private string NickName = "Edison Zhou";
}
(2)CascComp1.razor
<!--this is CascComp1.razor--><h3>Comp1: @NickName</h3><CascComp2></CascComp2>@code {[CascadingParameter]public string NickName { get; set; }
}
(3)CascComp2.razor
<!--this is CascComp2.razor--><h3>Comp2: @NickName</h3>@code {[CascadingParameter]public string NickName { get; set; }
}
要點:
(1)首先在CascCompSample.razor頁面,我們通過把CascComp1嵌套到CascadingValue里面來傳遞參數。
(2)其次在CascComp1和 CascComp2,不再需要顯式傳遞參數,只需要聲明CascadingParameter即可拿到值。
效果:
如果需要級聯傳遞多個參數,可以使用CascadingValue的嵌套,這里我們修改一下CascCompSample.razor組件,讓它可以共享兩個參數:
<!--this is CascCompSample.razor-->@page "/cascparamsample"<h3>This is the sample page</h3><CascadingValue Value="currentNickName" Name="NickName"><CascadingValue Value="currentAge" Name="Age"><CascComp1></CascComp1></CascadingValue>
</CascadingValue>@code
{private string currentNickName = "Edison Zhou";private int currentAge = 34;
}
修改CascComp1.razor,增加一個CascadingParameter屬性Age:
<!--this is CascComp1.razor--><h3>Comp1: @NickName - @Age</h3><CascComp2></CascComp2>@code {[CascadingParameter(Name="NickName")]public string NickName { get; set; }[CascadingParameter(Name="Age")]public int Age { get; set; }
}
CascComp2.razor修改同上,不再贅述。
這里需要注意的是:級聯值由父級中的 Name 屬性標識,與?[CascadingParameter]?屬性中的 Name 值匹配。對于只有一個該類型的參數而言,在子組件中CascadingParameter特性中無需指定Name。但對于如果有多個相同類型的級聯參數而言,最好加上Name名稱進行指定,以避免找不到。因此,這里也推薦在CascadingValue中指定Name,然后再CascadingParameter特性中指定Name。
最終效果:
使用AppState模式共享
在不同組件之間共享信息的另一種方法是使用 AppState 模式。
即創建一個定義要存儲的屬性的類,并將其注冊為作用域服務。在要設置或使用 AppState 值的任何組件中,注入該服務,然后可以訪問其屬性。不同于組件參數和級聯參數,AppState 中的值可用于應用程序中的所有組件,即使這些組件不是存儲該值的組件的子組件也是如此。
例如,創建一個包含銷售狀態的類:
public class PizzaSalesState
{public int PizzasSoldToday { get; set; }
}
然后,將該類注入到DI容器中:
builder.Services.AddScoped<PizzaSalesState>();
最后,在任意組件中通過依賴注入來訪問該屬性:
@page "/"
@using EDT.BlazorServer.App.Models
@inject PizzaSalesState salesState;<PageTitle>Index</PageTitle><h1>Hello, world!</h1>Welcome to your new app.<SurveyPrompt Title="Your Pizza Shop" />@*<Counter IncrementAmount="10" />*@
<p>Today, we've sold this many pizzas: @salesState.PizzasSoldToday</p>
<button @onclick="IncrementSales">Buy a Pizza</button>@code {private void IncrementSales(){salesState.PizzasSoldToday++;}
}
在本例中,由于我們已將計數器的值存儲在 AppState 范圍內服務中,因此計數會在頁面加載期間一直存在,并且對其他用戶可見。
最終效果:
小結
本篇,我們了解了數據如何在Blazor中共享。
下一篇,我們學習一下在Blazor中數據綁定的各種花樣。
參考資料
Microsoft Docs,《在Blazor應用程序中共享數據》
65號腕,《Blazor中的參數和級聯參數》
年終總結:Edison的2021年終總結
數字化轉型:我在傳統企業做數字化轉型
C#刷題:C#刷劍指Offer算法題系列文章目錄
.NET面試:.NET開發面試知識體系
.NET大會:2020年中國.NET開發者大會PDF資料