從 Blazor 元件存取數據
- 7 分鐘
吸引人的網站必須顯示可能隨時變更的動態內容。 瞭解如何從動態來源取得數據,例如資料庫或 Web 服務,是 Web 開發中的基本技術。
假設您在其更新的客戶面向網站上為披薩送貨公司工作。 且您有一系列的網頁配置,設計為 Blazor 元件。 現在,您想要將這些頁面填入您想要從資料庫取得的披薩、配料和訂單相關信息。
在此單元中,您將瞭解如何存取數據,並在 HTML 標記內轉譯,以向用戶顯示。
建立已註冊的數據服務
如果您想要建立動態網站來向使用者顯示變更資訊,您必須撰寫程式代碼以從某個位置取得該數據。 例如,假設您有一個資料庫來儲存公司銷售的所有披薩。 因為披薩種類總是更動,所以將它們硬編碼到網站HTML中是不明智的。 請改用 C# 程式代碼和 Blazor 來查詢資料庫,然後將詳細數據格式化為 HTML,讓使用者可以挑選其最愛。
在 Blazor Server 應用程式中,您可以建立已註冊的服務來代表數據源,並從中取得數據。
Note
您可以在 Blazor 應用程式中使用的數據來源包括關係資料庫、NoSQL 資料庫、Web 服務、各種 Azure 服務,以及其他許多系統。 您可以使用 Entity Framework、HTTP 用戶端和 ODBC (Open Database Connectivity) 等 .NET 技術來查詢這些來源。 這些技術已超出本課程模組的範圍。 在這裡,您將瞭解如何格式化和使用您從其中一個來源和技術取得的數據。
註冊服務的建立會從撰寫定義其屬性的類別開始。 以下是您可以撰寫來代表披薩的範例:
namespace BlazingPizza.Data;
public class Pizza
{
public int PizzaId { get; set; }
public string Name { get; set; }
public string Description { get; set; }
public decimal Price { get; set; }
public bool Vegetarian { get; set; }
public bool Vegan { get; set; }
}
類別會定義披薩的屬性和數據類型。 您必須確定這些屬性符合數據來源中的披薩架構。 在專案的 Data 資料夾中建立此類別,並使用名為 Data 的成員命名空間是合理的。 如果您想要的話,您可以選擇其他資料夾和命名空間。
接下來,您會定義服務:
namespace BlazingPizza.Data;
public class PizzaService
{
public Task<Pizza[]> GetPizzasAsync()
{
// Call your data access technology here
}
}
請注意,服務會使用異步呼叫來存取數據,並傳回 物件的集合 Pizza 。 數據源可能遠離執行 Blazor 程式代碼的伺服器。 在此情況下,請使用異步呼叫。 然後,如果數據源回應緩慢,則當您等候回應時,其他程式代碼可以繼續執行。
您會將一行新增至 Add Services to the containerProgram.cs 檔案中的 區段,以註冊服務:
...
// Add services to the container.
builder.Services.AddRazorPages();
builder.Services.AddServerSideBlazor();
// Register the pizzas service
builder.Services.AddSingleton<PizzaService>();
...
使用服務取得數據
現在您可以呼叫您所定義的服務,並在 Blazor 元件中獲取資料。 假設您有下列元件程式代碼,而且您想要在其中顯示披薩:
@page "/pizzas"
<h1>Choose your pizza</h1>
<p>We have all these delicious recipes:</p>
注入服務
您必須先使用相依性插入來新增服務,才能從元件呼叫服務。 在 @page 指令後面新增下列程式代碼,以插入服務:
@using BlazingPizza.Data
@inject PizzaService PizzaSvc
元件和服務通常位於不同的命名空間成員中,因此您必須包含 @using 指示詞。 這個指示詞的運作方式與 using C# 程式代碼檔案頂端的 語句相同。 此 @inject 指令會將服務新增至目前的元件,並初始化它的一個實例。 在指示詞中,指定服務類別的名稱。 接著輸入您希望用於此元件中服務實例的名稱。
覆寫 OnInitializedAsync 方法
一個呼叫服務並取得資料的好地方是在OnInitializedAsync方法中。 此事件會在元件初始化完成且收到其初始參數時引發,但在將頁面轉譯並顯示給使用者之前。 事件定義於 Blazor 元件的基類上。 您可以在程式代碼區塊中覆寫它,如下列範例所示:
protected override async Task OnInitializedAsync()
{
\\ Call the service here
}
呼叫服務以取得數據
當您呼叫服務時,請使用 await 關鍵詞,因為呼叫是異步的:
private Pizza[] todaysPizzas;
protected override async Task OnInitializedAsync()
{
todaysPizzas = await PizzaSvc.GetPizzasAsync();
}
向用戶顯示數據
從服務取得一些數據之後,您會想要向用戶顯示它。 在披薩範例中,我們預期服務會傳回使用者可以選擇的披薩清單。 Blazor 包含一組豐富的指示詞,可用來將此數據插入使用者看到的頁面。
檢查資料
首先,我們會透過檢查 todaysPizzas 集合是否為 null 來確定在載入比薩之前頁面顯示的內容。 若要在 Blazor 元件中執行條件式轉譯程式代碼,請使用 @if 指示詞:
@if (todaysPizzas == null)
{
<p>We're finding out what pizzas are available today...</p>
}
else
{
<!-- This markup will be rendered once the pizzas are loaded -->
}
只有在 C# 運算式傳回 @if 時,true 指示詞才會在其第一個程式碼區塊中轉譯標記。 您也可以使用 else if 代碼區塊來執行其他測試,如果條件成立,則渲染標記。 最後,如果先前沒有任何條件傳回 true,您可以指定程式碼區塊 else 來顯示程式碼。 透過檢查 null 程式碼區塊中的 @if,您可以確保 Blazor 不會在從服務取得資料之前嘗試顯示披薩詳細資料。
Note
Blazor 也會包括 @switch 指示詞,用於在可能傳回多個值的測試上轉譯標記。 指示 @switch 詞的運作方式與 C# switch 語句類似。
渲染物件的集合
如果 Blazor 在上述程式代碼中執行 else 語句,您就知道有些披薩是從服務取得的。 下一個工作是向用戶顯示這些披薩。 讓我們看看如何在簡單的 HTML 數據表中顯示數據。
當我們撰寫此頁面代碼時,我們不知道有多少披薩可用。 我們可以使用 @foreach 指令來迴圈遍歷 todaysPizzas 集合中的所有物件,並為每個物件渲染一行:
<table>
<thead>
<tr>
<th>Pizza Name</th>
<th>Description</th>
<th>Vegetarian?</th>
<th>Vegan?</th>
<th>Price</th>
</tr>
</thead>
<tbody>
@foreach (var pizza in todaysPizzas)
{
<tr>
<td>@pizza.Name</td>
<td>@pizza.Description</td>
<td>@pizza.Vegetarian</td>
<td>@pizza.Vegan</td>
<td>@pizza.Price</td>
</tr>
}
</tbody>
</table>
您可能想要比本範例中顯示的普通表格更加豐富的披薩顯示內容。 您可能想要格式化價格和其他值。 請與您的圖形設計工具合作,以開發更具吸引力的UI。 例如,包含每個披薩的圖片。
Note
Blazor 包含其他循環指示詞,例如 @for、 @while和 @do while。 這些指令會傳回重複的標記區塊。 它們的運作方式與對等的 C# for、 while和 do...while 循環類似。
在下一個單元中,您將註冊自己的數據服務!