练习 - 在 Blazor 应用程序中共享数据
现在,应用已连接到数据库,是时候添加订购和配置客户的披萨这一功能了。
Blazing Pizza 希望你生成允许客户更改其特价披萨尺寸的功能。 你需要存储订单,并且已选择在容器服务中存储应用程序状态。
在本练习中,你将向新的订单配置组件传递数据,并了解如何在 OrderState 作用域服务中存储应用的状态。
添加新的订单配置对话框
如果应用仍在运行,请停止它。
在 Visual Studio Code 中,右键单击 Shared 文件夹,然后选择“新建文件”。
输入 ConfigurePizzaDialog.razor 作为文件名。
为新的订购组件的 UI 输入以下代码:
@inject HttpClient HttpClient <div class="dialog-container"> <div class="dialog"> <div class="dialog-title"> <h2>@Pizza.Special.Name</h2> @Pizza.Special.Description </div> <form class="dialog-body"> <div> <label>Size:</label> <input type="range" min="@Pizza.MinimumSize" max="@Pizza.MaximumSize" step="1" /> <span class="size-label"> @(Pizza.Size)" (£@(Pizza.GetFormattedTotalPrice())) </span> </div> </form> <div class="dialog-buttons"> <button class="btn btn-secondary mr-auto" >Cancel</button> <span class="mr-center"> Price: <span class="price">@(Pizza.GetFormattedTotalPrice())</span> </span> <button class="btn btn-success ml-auto" >Order ></button> </div> </div> </div>
此组件是一个对话框,显示了选定的特价披萨,并允许客户选择披萨大小。
该组件需要索引页组件中的特价披萨才能访问披萨的成员值。
添加 Blazor
@code
块,以允许将参数传入组件:@code { [Parameter] public Pizza Pizza { get; set; } }
订购披萨
当客户选择披萨时,对话框应允许他们更改其披萨的尺寸。 让我们增强 index.razor 控件以添加此交互性。
在文件资源管理器中,展开“页面”,然后选择“Index.razor”。
将此代码添加到
@code
块中的List<PizzaSpecial>
变量下:Pizza configuringPizza; bool showingConfigureDialog;
在
OnInitializedAsync()
方法下添加此代码以创建披萨:void ShowConfigurePizzaDialog(PizzaSpecial special) { configuringPizza = new Pizza() { Special = special, SpecialId = special.Id, Size = Pizza.DefaultSize }; showingConfigureDialog = true; }
通过允许客户选择披萨的
<li>
标记,允许网页调用服务器端ShowConfigurePizzaDialog
方法。 将<li>
行替换为此代码:<li @onclick="@(() => ShowConfigurePizzaDialog(special))" style="background-image: url('@special.ImageUrl')">
当客户选择披萨时,服务器将执行
ShowConfigurePizzaDialog
方法,该方法使用特价披萨数据创建披萨,并将showingConfigureDialog
变量设置为true
。页面需要一种方法来显示新的
ConfigurePizzaDialog
组件。 将此代码添加到@code
块的上方:@if (showingConfigureDialog) { <ConfigurePizzaDialog Pizza="configuringPizza" /> }
整个
index.razor
文件现在应如以下示例所示:@page "/" @inject HttpClient HttpClient @inject NavigationManager NavigationManager <div class="main"> <h1>Blazing Pizzas</h1> <ul class="pizza-cards"> @if (specials != null) { @foreach (var special in specials) { <li @onclick="@(() => ShowConfigurePizzaDialog(special))" style="background-image: url('@special.ImageUrl')"> <div class="pizza-info"> <span class="title">@special.Name</span> @special.Description <span class="price">@special.GetFormattedBasePrice()</span> </div> </li> } } </ul> </div> @if (showingConfigureDialog) { <ConfigurePizzaDialog Pizza="configuringPizza" /> } @code { List<PizzaSpecial> specials = new(); Pizza configuringPizza; bool showingConfigureDialog; protected override async Task OnInitializedAsync() { specials = await HttpClient.GetFromJsonAsync<List<PizzaSpecial>>(NavigationManager.BaseUri + "specials"); } void ShowConfigurePizzaDialog(PizzaSpecial special) { configuringPizza = new Pizza() { Special = special, SpecialId = special.Id, Size = Pizza.DefaultSize }; showingConfigureDialog = true; } }
选择 F5 或“运行”。 然后选择“开始调试”。
选择披萨并观看新对话框的出现。
处理订单的状态
此时,应用会显示配置对话框,但不允许取消或继续订购披萨。 若要管理订单的状态,需要添加新的订单状态容器服务。
如果应用仍在运行,请停止它。
在 BlazingPizza 文件夹中创建新文件夹。 将其命名为 Services。
在 Services 文件夹中创建新文件。 将其命名为 OrderState.cs。
为类输入以下代码:
namespace BlazingPizza.Services; public class OrderState { public bool ShowingConfigureDialog { get; private set; } public Pizza ConfiguringPizza { get; private set; } public Order Order { get; private set; } = new Order(); public void ShowConfigurePizzaDialog(PizzaSpecial special) { ConfiguringPizza = new Pizza() { Special = special, SpecialId = special.Id, Size = Pizza.DefaultSize, Toppings = new List<PizzaTopping>(), }; ShowingConfigureDialog = true; } public void CancelConfigurePizzaDialog() { ConfiguringPizza = null; ShowingConfigureDialog = false; } public void ConfirmConfigurePizzaDialog() { Order.Pizzas.Add(ConfiguringPizza); ConfiguringPizza = null; ShowingConfigureDialog = false; } }
你将看到 index.razor 组件中当前有一些代码,我们可以将这些代码移动到新类中。 下一步是使此服务在应用中可用。
在文件资源管理器中,选择“Program.cs”。
在以
builder.Services.
开头的行的文件部分中,添加以下行:builder.Services.AddScoped<OrderState>();
在上一个练习中,我们在此处添加了数据库上下文。 此代码添加新的
OrderState
服务。 此代码准备就绪后,我们现在可以在index.razor
组件中使用它。将下面的
using
指令添加到文件的顶部来解析OrderState
类:using BlazingPizza.Services;
在文件资源管理器中,展开“页面”,然后选择“Index.razor”。
在文件顶部的
@inject NavigationManager NavigationManager
下,添加以下代码:@using BlazingPizza.Services @inject OrderState OrderState
从
@code
块中移除configuringPizza
、showingConfigureDialog
和ShowConfigurePizzaDialog()
。 它现在应如下所示:@code { List<PizzaSpecial> specials = new List<PizzaSpecial>(); protected override async Task OnInitializedAsync() { specials = await HttpClient.GetFromJsonAsync<List<PizzaSpecial>>(NavigationManager.BaseUri + "specials"); } }
现在出现了一些错误,所有代码都引用了已删除的内容。
将对
ShowConfigurePizzaDialog(special))
的调用更改为使用 OrderState 版本:<li @onclick="@(() => OrderState.ShowConfigurePizzaDialog(special))" style="background-image: url('@special.ImageUrl')">
更改对布尔值
showingConfigureDialog
的引用:@if (OrderState.ShowingConfigureDialog)
通过使用
configuringPizza
更改参数:<ConfigurePizzaDialog Pizza="OrderState.ConfiguringPizza" />
选择 F5 或“运行”。 然后选择“开始调试”。
如果所有内容都正确,你将看不到任何区别。 对话框的显示方式与之前相同。
取消和进行披萨订购
你可能已经注意到 OrderState 类中有两种我们尚未使用的方法。 CancelConfigurePizzaDialog
和 ConfirmConfigurePizzaDialog
方法将关闭对话框,并在客户确认订购后将披萨添加到 Order
对象。 让我们将这些方法连接到配置对话框按钮。
如果应用仍在运行,请停止它。
在文件资源管理器中,展开“共享”。 然后选择“ConfigurePizzaDialog.razor”。
在
@code
块中,添加两个新参数:@code { [Parameter] public Pizza Pizza { get; set; } [Parameter] public EventCallback OnCancel { get; set; } [Parameter] public EventCallback OnConfirm { get; set; } }
这些按钮现在可以添加
@onclick
指令。 将对话框按钮的当前代码更改为此标记:<div class="dialog-buttons"> <button class="btn btn-secondary mr-auto" @onclick="OnCancel">Cancel</button> <span class="mr-center"> Price: <span class="price">@(Pizza.GetFormattedTotalPrice())</span> </span> <button class="btn btn-success ml-auto" @onclick="OnConfirm">Order ></button> </div>
最后一步是传递用于取消和确认订单的
OrderState
方法。 在文件资源管理器中,展开“页面”。 然后选择“Index.razor”。更改对
ConfigurePizzaDialog
组件的调用的代码:<ConfigurePizzaDialog Pizza="OrderState.ConfiguringPizza" OnCancel="OrderState.CancelConfigurePizzaDialog" OnConfirm="OrderState.ConfirmConfigurePizzaDialog" />
选择 F5 或“运行”。 然后选择“开始调试”。
应用现在应允许客户取消订单或向订单中添加已配置的披萨。 当披萨大小发生变化时,我们无法显示当前订单或更新价格。 我们将在下一练习中添加这些功能。