在 Blazor 應用程式中共用資料
Blazor 有幾種方式可在元件之間共用資訊。 您可以使用元件參數或串聯參數,將值從父元件傳送至子元件。 AppState 模式是另一種方法,可用來儲存值並從應用程式中的任何元件存取值。
假設您正在建置新的披薩外送網站。 多個披薩應該以相同的方式顯示在首頁上。 您想要藉由轉譯每個披薩的子元件來顯示披薩。 現在,您想要將識別碼傳遞至該子元件,以決定其會顯示的披薩。 您也想要在多個元件上儲存並顯示值,以顯示今天的披薩銷售總數。
在本單元中,您將了解可用來在兩個以上的 Blazor 元件之間共用值的三種不同技術。
使用元件參數來與其他元件共用資訊
在 Blazor Web 應用程式中,每個元件都會轉譯一部分的 HTML。 有些元件會轉譯整個頁面,有些元件則只會轉譯較小的標記片段,例如資料表、表單或單一控制項。 如果您的元件只會轉譯一段標記,您就必須將其作為父元件內的子元件來使用。 子元件也可以是在其內轉譯的其他較小元件的父元件。 子元件也稱為巢狀元件。
在這個有父元件和子元件的階層中,您可以使用元件參數讓其彼此共用資訊。 在子元件上定義這些參數,然後在父元件中設定其值。 例如,如果您有顯示披薩圖片的子元件,則可以使用元件參數來傳遞披薩識別碼。 子元件會透過識別碼查閱披薩,並取得圖片和其他資料。 如果您想要顯示許多不同的披薩,就可以在相同的父頁面上多次使用此子元件,並向每個子元件傳遞不同的識別碼。
首先,請在子元件中定義元件參數。 其會定義為 C# 公用屬性,並使用 [Parameter]
屬性加以裝飾:
<h2>New Pizza: @PizzaName</h2>
<p>@PizzaDescription</p>
@code {
[Parameter]
public string PizzaName { get; set; }
[Parameter]
public string PizzaDescription { get; set; } = "The best pizza you've ever tasted."
}
因為元件參數是子元件的成員,所以您可以使用 Blazor 的保留 @
符號,並於後面加上其名稱,而在 HTML 中轉譯這些參數。 此外,上述程式碼會指定 PizzaDescription
參數的預設值。 如果父元件未傳遞值,則會轉譯此值。 否則,會由從父元件傳遞的值加以覆寫。
您也可以在專案中使用自訂類別來作為元件參數。 請考慮用來描述配料的這個類別:
public class PizzaTopping
{
public string Name { get; set; }
public string Ingredients { get; set; }
}
您可以像參數值一樣地使用該類別作為元件參數,使用點語法來存取該類別的個別屬性:
<h2>New Topping: @Topping.Name</h2>
<p>Ingredients: @Topping.Ingredients</p>
@code {
[Parameter]
public PizzaTopping Topping { get; set; }
}
在父元件中,使用子元件標籤的屬性來設定參數值。 簡單的元件可以直接設定。 透過以自訂類別為基礎的參數,您會使用內嵌 C# 程式碼,來建立該類別的新執行個體並設定其值:
@page "/pizzas-toppings"
<h1>Our Latest Pizzas and Topping</h1>
<Pizza PizzaName="Hawaiian" PizzaDescription="The one with pineapple" />
<PizzaTopping Topping="@(new PizzaTopping() { Name = "Chilli Sauce", Ingredients = "Three kinds of chilli." })" />
使用串聯參數來共用資訊
當您想要將值傳遞給元件的直屬子系時,元件參數會正常運作。 當您的階層很深,有不斷拓展的子系時,情況就會變得麻煩。 系統不會自動將元件參數從上階元件傳遞給下階元件,也不會在階層中一路傳遞下去。 為了簡潔地處理這個問題,Blazor 納入了串聯參數。 當您在元件中設定串聯參數的值時,系統會將其值自動提供給位於任何深度的所有子元件。
在父元件中,使用 <CascadingValue>
標籤會指定要串聯至所有子元件的資訊。 此標籤會實作為內建 Blazor 元件。 在該標籤內轉譯的任何元件都能夠存取該值。
@page "/specialoffers"
<h1>Special Offers</h1>
<CascadingValue Name="DealName" Value="Throwback Thursday">
<!-- Any descendant component rendered here will be able to access the cascading value. -->
</CascadingValue>
在子元件中,您可以使用元件成員並為其裝飾上 [CascadingParameter]
屬性,而能夠存取串聯值。
<h2>Deal: @DealName</h2>
@code {
[CascadingParameter(Name="DealName")]
private string DealName { get; set; }
}
因此在本範例中,<h2>
標籤會有 Deal: Throwback Thursday
內容,因為該串聯值由上階元件設定。
注意
就元件參數而言,如果您有更複雜的需求,則可以將物件作為串聯參數來進行傳遞。
在上述範例中,串聯值會由父元件中的 Name
屬性加以識別,且此屬性會與 [CascadingParameter]
屬性中的 Name
值進行比對。 您可以選擇性地省略這些名稱,在此情況下,屬性會依類型進行比對。 當您只有一個該型別的參數時,省略名稱的效果很好。 如果您想要串聯兩個不同的字串值,則必須使用參數名稱來避免任何歧異。
使用 AppState 來共用資訊
另一種在不同元件之間共用資訊的方法是使用 AppState 模式。 您可以建立類別來定義您想要儲存的屬性,並將該類別註冊為範圍服務。 在您想要設定或使用 AppState 值的任何元件中,您可以插入服務,然後存取其屬性。 不同於元件參數和串聯參數,AppState 中的值可供應用程式中的所有元件使用,甚至可供儲存了值但並非元件子系的元件使用。
例如,請考慮這個儲存了銷售相關數據的類別:
public class PizzaSalesState
{
public int PizzasSoldToday { get; set; }
}
您會將此類別新增為 Program.cs 檔案中的範圍服務:
...
// Add services to the container
builder.Services.AddRazorPages();
builder.Services.AddServerSideBlazor();
// Add the AppState class
builder.Services.AddScoped<PizzaSalesState>();
...
現在,在您想要設定或擷取 AppState 值的任何元件中,您可以插入此類別,然後存取屬性:
@page "/"
@inject PizzaSalesState SalesState
<h1>Welcome to Blazing Pizzas</h1>
<p>Today, we've sold this many pizzas: @SalesState.PizzasSoldToday</p>
<button @onclick="IncrementSales">Buy a Pizza</button>
@code {
private void IncrementSales()
{
SalesState.PizzasSoldToday++;
}
}
注意
此程式碼會實作計數器,當使用者選取按鈕時便會遞增值,情況與 Blazor 教學課程 - 建置您的第一個 Blazor 應用程式中的範例極為類似。 差別在於,在此情況下,因為我們已將計數器的值儲存到 AppState 範圍服務中,所以計數會跨頁面載入持續下去,而且其他使用者可以看到。
在下一個單元中,您會自己試試!