练习 - 在 Blazor 应用中使用 JavaScript 库

已完成

客户将披萨添加到订单后,可以选择 X 图标从订单中删除披萨,而无需确认。 为了防止客户意外地从订单中删除披萨,披萨公司希望你添加一个删除商品的确认提示。

披萨公司还希望客户能实时查看订单进度。 你需要更新订单详细信息页以持续查询订单状态,并向客户提供页面正在更新的反馈。

在本练习中,你将通过使用 Blazor 组件的 JS 互操作在客户端调用 JavaScript 来扩展披萨配送公司的现有应用。 需要与第三方 JavaScript 库集成以改进取消弹出窗口,并从 JavaScript 调用 Blazor 方法以获取客户订单的实时状态。

克隆现有应用

要使用 Blazor,请确保已安装 .NET 8.0 SDK。 有关详细信息,请参阅检查是否已正确安装所有项

  1. 打开 Visual Studio Code,通过从顶部菜单中选择“终端”>“新终端”来打开集成终端。

  2. 在终端中,更改到要创建项目的目录。

  3. 运行以下命令,将应用从 GitHub 克隆到本地子目录。

    git clone https://github.com/MicrosoftDocs/mslearn-build-interactive-components-blazor.git BlazingPizza
    
  4. 在顶部菜单栏中,选择“文件”>“打开文件夹”。

  5. 在“打开文件夹”对话框中,浏览到 BlazingPizza 文件夹,然后选择“选择文件夹”。

    如果 Visual Studio Code 提示缺少资产或未解析的依赖项,请选择“是”或“还原”。

  6. 若要运行应用并检查一切是否运行正常,请按 F5 或选择“运行”>“开始调试”。

  7. 在 Web 应用中,选择一些披萨并将其添加到订单中。 如果订单列表中有一些披萨,请选择其中一个披萨旁边的 X,并验证商品是否在没有任何提示的情况下消失。

  8. Shift+F5 或选择“运行”>“停止调试”以停止应用。

重构订单流程

若要使用 JS 互操作,请注入 IJSRuntime 抽象。

  1. 在 Visual Studio Code 资源管理器中,展开“页”,然后选择“Index.razor”。

  2. 在 Index.razor 文件中的 @inject OrderState OrderState 语句后面,按如下所示添加 IJSRuntime 注入。

    @inject OrderState OrderState
    @inject IJSRuntime JavaScript
    
  3. 目前,删除披萨功能的 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">&times;</span>
    </button>
    
  4. 在文件末尾的 @code 指令中,添加一个新方法来调用本机 JavaScript confirm 函数。 如果客户从提示中选择“确定”,则方法将调用 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,则将从订单中删除披萨。

  5. F5 或选择“运行”>“开始调试”。

  6. 在应用中,将一些披萨添加到你的订单中。

  7. 如果订单中有几个披萨,请选择其中一个披萨旁边的 X。 此时将显示一个标准 JavaScript 确认对话框。

    Screenshot of the default JavaScript confirm dialog.

  8. 选择“确定”,并验证是否已从订单中删除披萨。 选择另一个披萨旁边的“X”,在确认对话框中选择“取消”,然后验证披萨是否仍保留在订单中。

  9. Shift+F5 或选择“运行”>“停止调试”以停止应用。

将第三方 JavaScript 库添加到 Blazor 应用

披萨公司希望确认对话框中按钮上的文本更清晰,并希望在对话框中使用其品牌和样式。 经过一些研究,你决定使用名为 SweetAlert 的小型 JavaScript 库作为标准对话框的良好替代方法。

  1. 在 Visual Studio Code 资源管理器中,展开“页”,然后选择“_Host.cshtml”。

  2. _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 库现在可以在客户端调用。

  3. 若要使用新库,请更新 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 对象。

  4. 在 Visual Studio Code 中,按 F5 或选择“运行”>“开始调试”。

  5. 验证 confirm 对话框现在是否有两个按钮,即“否,在我的订单中保留它”和“是,删除披萨”,以及它们是否按预期运行。

    Screenshot showing the SweetAlert dialog box.

  6. Shift+F5 或选择“运行”>“停止调试”以停止应用。

更新订单页以显示实时订单状态

客户下披萨订单后,“我的订单”页使用 OrderDetail 组件显示订单的当前状态。 披萨公司希望客户能实时查看订单进度。 需要更新组件以从 JavaScript 调用 .NET 方法,以持续获取订单状态,直到状态显示已送达。

  1. 在 Visual Studio Code 资源管理器中,展开“页”,然后选择“OrderDetail.razor”。

  2. 在 OrderDetail.razor 文件中,在组件顶部的最后一个 @inject 语句下添加以下声明。

    @implements IDisposable
    

    @implements 声明允许你定义 Dispose 方法。

  3. 将旋转图标添加到页面以向客户提供页面正在更新的反馈。 在 <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>
    }
    
  4. @code 指令的 OrderId 属性声明下,添加以下成员。

    bool IsOrderIncomplete =>
        orderWithStatus is null || orderWithStatus.IsDelivered == false;
    
    PeriodicTimer timer = new(TimeSpan.FromSeconds(3));
    
  5. 使用下面的代码替换现有 OnParametersSetAsync 方法:

    protected override async Task OnParametersSetAsync() =>
        await GetLatestOrderStatusUpdatesAsync();
    

    此代码现在调用 GetLatestOrderStatusUpdatesAsync 方法以更新订单状态。

  6. 在更新的 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 异步等待下一个时钟周期。 订单交付后,动画旋转图标将被删除,页面显示最终订单状态。

  7. 在 Visual Studio Code 中,按 F5 或选择“运行”>“开始调试”。

  8. 在应用中,订购一个披萨。 转到“我的订单”屏幕,验证在订单未完成时是否显示动画红点,以及是否在状态显示“已送达”时动画红点消失。

    Animation showing the order status changing in real-time.

  9. Shift+F5 或选择“运行”>“停止调试”以停止应用。