练习 - 在 Blazor 应用中使用 JavaScript 库
在客户将披萨添加到订单后,他们可以选择 X 图标,在不确认的情况下从订单中删除披萨。 为了防止客户意外从他们的订单中删除披萨,披萨公司希望你添加一个确认提示,以便删除项目。
披萨公司还希望客户了解订单的实时进度。 需要更新订单详细信息页以持续查询订单状态,并向客户提供页面正在更新的反馈。
在本练习中,你将使用 Blazor 组件中的 JS 互作在客户端调用 JavaScript 来扩展披萨交付公司的现有应用。 与第三方 JavaScript 库集成以改进取消弹出窗口,并从 JavaScript 调用 Blazor 方法以获取客户订单的实时状态。
克隆现有应用
本模块使用 .NET 9.0 SDK。 通过在首选命令终端中运行以下命令,确保你已安装 .NET 9.0:
dotnet --list-sdks
将显示类似于以下示例的输出:
8.0.100 [C:\Program Files\dotnet\sdk]
9.0.100 [C:\Program Files\dotnet\sdk]
确保列出了以 9
开头的版本。 如果未列出或找不到命令, 请安装最新的 .NET 9.0 SDK。
有关详细信息,请参阅 使用 Blazor 通过 ASP.NET Core 生成第一个 Web 应用。
打开 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 资源管理器中,展开 Pages,然后选择 _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 库现在可用于在客户端调用。
若要使用新库,请按如下所示更新
RemovePizzaConfirmation
Index.razor 文件中的方法。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 或选择“ 运行>停止调试 ”以停止应用。