簡體   English   中英

Blazor WASM 中的意外 UI 綁定行為

[英]Unexpected UI binding behavior in Blazor WASM

我在 Blazor WASM 和 Blazor 服務器之間的 UI 綁定行為中遇到了意外(且莫名其妙)的差異。 鑒於以下 razor 組件,“發送”按鈕在請求期間被正確禁用,在 Blazor 服務器和 Blazor WASM 中:

<MudButton Disabled="isProcessing" OnClick="Submit">Send</MudButton>

@code {
    private bool isProcessing;

    private async Task Submit()
    {
        isProcessing = true;
        var contacts = await Mediator.Send(getContacts);
        isProcessing = false;
    }    
}

在向提交方法添加第二個等待調用( IsValidAsync() )后,該按鈕現在在 Blazor WASM 中的請求期間保持啟用狀態,我認為這是錯誤的。 在 Blazor 服務器中,它仍然按預期被禁用:

private async Task Submit()
{
    if (await validator.IsValidAsync())
    {
        isProcessing = true;
        var contacts = await Mediator.Send(getContacts);
        isProcessing = false;
    }
}

為什么這種綁定在 Blazor WASM 中不起作用有明確的原因嗎? 或者這是 Blazor 中的一個明顯錯誤?

規則是您可以免費獲得 2 個隱含的 StatehasChanged() 調用,1 個在事件處理程序之前和 1 個之后。

因此,您在第一次等待中獲得了“免費更新”,但是當您的代碼中有更多步驟(需要輸出)時,您需要幫助:

private async Task Submit()
{
   if (await validator.IsValidAsync())  // consumes the first StateHasChanged
   {
      isProcessing = true;

      StateHasChanged();    // request an update

      var contacts = await Mediator.Send(getContacts); // update UI in background
      isProcessing = false;     
   }
   // one implied StateHasChanged for free again
}

這種模式應該用在 Server 和 Wasm 上。 原始代碼在服務器上為您工作的原因尚不清楚。 這可能是來自 IsValidAsync() 的僥幸,具有非異步代碼路徑。

我很驚訝它的行為不同,但 Server 和 WASM 之間存在顯着差異,這可以解釋發生了什么。 我對 MudBlazor 並不完全熟悉,所以我不確定 MudBlazor 內部是如何工作的。

不同之處在於瀏覽器對於所有操作只有一個線程。 服務器盡可能多的可用在服務器實例上,這幾乎在所有情況下都不止一個。

嘗試:

private async Task Submit()
{
    isProcessing = true;
    if (await validator.IsValidAsync())
    {
        var contacts = await Mediator.Send(getContacts);
    }
    isProcessing = false;
}

或者

private async Task Submit()
{
    if (await validator.IsValidAsync())
    {
        isProcessing = true;
        await InvokeAsync(StateHasChanged);
        var contacts = await Mediator.Send(getContacts);
        isProcessing = false;
    }
}

事件處理程序基本上是這樣做的:

var task = Submit();
StateHasChanged();
if (!task.IsCompleted || !task.IsCanceled)
{
  await task;
  StateHasChanged();
}

您可以在ComponentBase中看到這種模式。 它說如果任務成功,那么我們更新 UI,等待它完成,然后再次更新 UI。 如果它沒有產生,那么我們會在它完成后更新 UI。 我的服務器代碼和 WASM 代碼的行為相同 - 確定您的代碼有何不同。

您的代碼在if (await validator.IsValidAsync())中產生,因此在設置isProcessing之前調用第一個StateHasChanged

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM