练习 - 在 Blazor 应用中使用 JavaScript 库
客户将披萨添加到订单后,可以选择 X 图标从订单中删除披萨,而无需确认。 为了防止客户意外地从订单中删除披萨,披萨公司希望你添加一个删除商品的确认提示。
披萨公司还希望客户能实时查看订单进度。 你需要更新订单详细信息页以持续查询订单状态,并向客户提供页面正在更新的反馈。
在本练习中,你将通过使用 Blazor 组件的 JS 互操作在客户端调用 JavaScript 来扩展披萨配送公司的现有应用。 需要与第三方 JavaScript 库集成以改进取消弹出窗口,并从 JavaScript 调用 Blazor 方法以获取客户订单的实时状态。
克隆现有应用
要使用 Blazor,请确保已安装 .NET 8.0 SDK。 有关详细信息,请参阅检查是否已正确安装所有项。
打开 Visual Studio Code,通过从顶部菜单中选择“终端”>“新终端”来打开集成终端。
在终端中,更改到要创建项目的目录。
运行以下命令,将应用从 GitHub 克隆到本地子目录。
git clone https://github.com/MicrosoftDocs/mslearn-build-interactive-components-blazor.git BlazingPizza
在顶部菜单栏中,选择“文件”>“打开文件夹”。
在“打开文件夹”对话框中,浏览到 BlazingPizza 文件夹,然后选择“选择文件夹”。
如果 Visual Studio Code 提示缺少资产或未解析的依赖项,请选择“是”或“还原”。
若要运行应用并检查一切是否运行正常,请按 F5 或选择“运行”>“开始调试”。
在 Web 应用中,选择一些披萨并将其添加到订单中。 如果订单列表中有一些披萨,请选择其中一个披萨旁边的 X,并验证商品是否在没有任何提示的情况下消失。
按 Shift+F5 或选择“运行”>“停止调试”以停止应用。
重构订单流程
若要使用 JS 互操作,请注入 IJSRuntime
抽象。
在 Visual Studio Code 资源管理器中,展开“页”,然后选择“Index.razor”。
在 Index.razor 文件中的
@inject OrderState OrderState
语句后面,按如下所示添加IJSRuntime
注入。@inject OrderState OrderState @inject IJSRuntime JavaScript
目前,删除披萨功能的
onclick
事件会直接调用OrderState.RemoveConfiguredPizza(configuredPizza))
方法。 将整个<a @onclick="@(() => OrderState.RemoveConfiguredPizza(configuredPizza))" class="delete-item">❌</a>
元素替换为以下代码:<button type="button" class="close text-danger" aria-label="Close" @onclick="@(async () => await RemovePizzaConfirmation(configuredPizza))"> <span aria-hidden="true">×</span> </button>
在文件末尾的
@code
指令中,添加一个新方法来调用本机 JavaScriptconfirm
函数。 如果客户从提示中选择“确定”,则方法将调用OrderState.RemoveConfiguredPizza
以从订单中删除披萨。 否则,披萨仍按顺序排列。async Task RemovePizzaConfirmation(Pizza removePizza) { if (await JavaScript.InvokeAsync<bool>( "confirm", $"""Do you want to remove the "{removePizza.Special!.Name}" from your order?""")) { OrderState.RemoveConfiguredPizza(removePizza); } }
服务器使用 IJSRuntime.InvokeAsync 方法在客户端调用
confirm
函数。 调用的响应返回值bool
。 如果确认对话框的结果为true
,则将从订单中删除披萨。按 F5 或选择“运行”>“开始调试”。
在应用中,将一些披萨添加到你的订单中。
如果订单中有几个披萨,请选择其中一个披萨旁边的 X。 此时将显示一个标准 JavaScript 确认对话框。
选择“确定”,并验证是否已从订单中删除披萨。 选择另一个披萨旁边的“X”,在确认对话框中选择“取消”,然后验证披萨是否仍保留在订单中。
按 Shift+F5 或选择“运行”>“停止调试”以停止应用。
将第三方 JavaScript 库添加到 Blazor 应用
披萨公司希望确认对话框中按钮上的文本更清晰,并希望在对话框中使用其品牌和样式。 经过一些研究,你决定使用名为 SweetAlert 的小型 JavaScript 库作为标准对话框的良好替代方法。
在 Visual Studio Code 资源管理器中,展开“页”,然后选择“_Host.cshtml”。
在 _Host.cshtml 文件的末尾,在
<script src="_framework/blazor.server.js"></script>
行之后、</body>
行之前添加以下script
元素以包括 SweetAlert 库。<script src="https://cdn.jsdelivr.net/npm/sweetalert@latest/dist/sweetalert.min.js"></script>
SweetAlert 库现在可以在客户端调用。
若要使用新库,请更新 Index.razor 文件中的
RemovePizzaConfirmation
方法,如下所示。async Task RemovePizzaConfirmation(Pizza removePizza) { var messageParams = new { title = "Remove Pizza?", text = $"""Do you want to remove the "{removePizza.Special!.Name}" from your order?""", icon = "warning", buttons = new { abort = new { text = "No, leave it in my order", value = false }, confirm = new { text = "Yes, remove pizza", value = true } }, dangerMode = true }; if (await JavaScript.InvokeAsync<bool>("swal", messageParams)) { OrderState.RemoveConfiguredPizza(removePizza); } }
"swal"
名称是 JavaScript 函数的标识符,它来自第三方 sweetalert.js 引用。 调用swal
函数的代码类似于confirm
。 更新的大部分内容是函数如何接收参数。 SweetAlert 接受一个包含它需要的所有设置的 JSON 对象。在 Visual Studio Code 中,按 F5 或选择“运行”>“开始调试”。
验证
confirm
对话框现在是否有两个按钮,即“否,在我的订单中保留它”和“是,删除披萨”,以及它们是否按预期运行。按 Shift+F5 或选择“运行”>“停止调试”以停止应用。
更新订单页以显示实时订单状态
客户下披萨订单后,“我的订单”页使用 OrderDetail
组件显示订单的当前状态。 披萨公司希望客户能实时查看订单进度。 需要更新组件以从 JavaScript 调用 .NET 方法,以持续获取订单状态,直到状态显示已送达。
在 Visual Studio Code 资源管理器中,展开“页”,然后选择“OrderDetail.razor”。
在 OrderDetail.razor 文件中,在组件顶部的最后一个
@inject
语句下添加以下声明。@implements IDisposable
此
@implements
声明允许你定义Dispose
方法。将旋转图标添加到页面以向客户提供页面正在更新的反馈。 在
<div class="track-order-details">
中的@foreach
语句上方,添加以下代码:@if (IsOrderIncomplete) { <div class="spinner-grow text-danger float-right" role="status"> <span class="sr-only">Checking your order status...</span> </div> }
在
@code
指令的OrderId
属性声明下,添加以下成员。bool IsOrderIncomplete => orderWithStatus is null || orderWithStatus.IsDelivered == false; PeriodicTimer timer = new(TimeSpan.FromSeconds(3));
使用下面的代码替换现有
OnParametersSetAsync
方法:protected override async Task OnParametersSetAsync() => await GetLatestOrderStatusUpdatesAsync();
此代码现在调用
GetLatestOrderStatusUpdatesAsync
方法以更新订单状态。在更新的
OnParametersSetAsync
方法后面添加以下方法。protected override Task OnAfterRenderAsync(bool firstRender) => firstRender ? StartPollingTimerAsync() : Task.CompletedTask; async Task GetLatestOrderStatusUpdatesAsync() { try { orderWithStatus = await HttpClient.GetFromJsonAsync<OrderWithStatus>( $"{NavigationManager.BaseUri}orders/{OrderId}"); } catch (Exception ex) { invalidOrder = true; Console.Error.WriteLine(ex); } } async Task StartPollingTimerAsync() { while (IsOrderIncomplete && await timer.WaitForNextTickAsync()) { await GetLatestOrderStatusUpdatesAsync(); StateHasChanged(); } } public void Dispose() => timer.Dispose();
OrderDetail
组件在呈现页面后开始轮询,并在订单送达时停止轮询。 当订单状态为“未完成”时,StartPollingTimerAsync
函数使用 PeriodicTimer 异步等待下一个时钟周期。 订单交付后,动画旋转图标将被删除,页面显示最终订单状态。在 Visual Studio Code 中,按 F5 或选择“运行”>“开始调试”。
在应用中,订购一个披萨。 转到“我的订单”屏幕,验证在订单未完成时是否显示动画红点,以及是否在状态显示“已送达”时动画红点消失。
按 Shift+F5 或选择“运行”>“停止调试”以停止应用。