【问题标题】:when to call StateHasChanged() in Blazor component何时在 Blazor 组件中调用 StateHasChanged()
【发布时间】:2021-11-07 03:53:32
【问题描述】:

我想弄清楚何时需要调用 StateHasChanged()。我知道通过 Javascript 更改值时,可能需要强制 blazor 组件呈现页面。在下面的代码中,我有一个名为 HandleClick 的方法来处理按钮单击,我故意注释掉 StateHasChanged() 。 HandleClick 方法本身调用Javascript 来设置Part 2 中元素的值。由于 Blazor 组件不知道 fromJs 值的变化,所以 Part 1 中的值在点击后不会更新。但问题是为什么当我再次单击按钮时 Part 1 中的值会发生变化。

@page "/ExampleY"

@using Microsoft.AspNetCore.Components
@using Microsoft.JSInterop
@inject IJSRuntime JSRuntime

<div class="p-2">
    <p class="alert-info p-3">
       Part 1.  Get value via JS call: <strong>@(fromJs ?? "Empty")</strong>
    </p>

    <p class="alert-success p-3">
        Part 2. Set value via JS call: <strong @ref="element"></strong>
    </p>

    <button class="btn btn-success" @onclick="HandleClick">Click to Call JS</button>
</div>

@code {
    private string fromJs;
    private ElementReference element;

    public async void HandleClick()
    {
        fromJs = await JSRuntime.InvokeAsync<string>("setText", element, "Hello from JS call!");
        // StateHasChanged();
    }

}

【问题讨论】:

    标签: asp.net blazor


    【解决方案1】:

    这与 JavaScript 互操作无关。

    当您进行此更改时:

    //public async void HandleClick()
      public async Task HandleClick()
    

    那么这两个部分将同时更新。

    几乎总是避免async void。它是 Timer.Elapsed 等老式事件处理程序的最后手段。 Blazor 事件可以返回 void 或 [async] Task。

    问题是为什么当我再次单击按钮时第 1 部分中的值会发生变化。

    ButtonClick 总是会导致重新渲染。但是由于async void 这可能发生在之前 fromJs 被分配。 await JSRuntime.InvokeAsync(...) 中的 await 允许这样做。在下一次单击时,您将看到 fromJs 的先前值出现在第 1 部分中。
    使用"Hello from JS call! "+DateTime.Now 来查看这个版本。

    【讨论】:

      【解决方案2】:

      Blazor“内部”事件处理程序代码如下所示:

      var task = InvokeAsync(EventMethod);
      StateHasChanged();
      if (!task.IsCompleted)
      {
          await task;
          StateHasChanged();
      }
      

      如果您将任务传递为 void,如下所示:

      public async void HandleClick()
      

      没有什么可以等待的。 task 已完成,最终的渲染事件永远不会发生。这就是为什么任何async 处理程序(即带有等待的方法),如上所述,必须返回一个任务。

      所以回答你的问题。第 1 部分中的值已更新,但在重新渲染组件之后 - 没有要等待的任务。当您再次单击该按钮时,您会显示“最后一个”值,即最后一次单击按钮的值,而不是当前单击。如果您将文本设置为点击时间,您会看到这一点。

      【讨论】:

      • 是的,正如您在此处显示的,总是有 1 次调用 StateHasChanged()。第二个用于异步处理程序。我在找这件作品。
      • @HenkHolterman。您会在许多 Blazor 代码库中看到相同的基本模式 - 就像 ComponentBase 如何运行 OnInitializedAsync 和 OnParametersSetAsync。
      猜你喜欢
      • 2020-09-28
      • 2020-07-13
      • 2021-03-21
      • 2021-08-02
      • 1970-01-01
      • 2021-01-23
      • 2020-08-07
      • 2020-08-11
      • 1970-01-01
      相关资源
      最近更新 更多