使用IJSRuntime Blazor时的屏幕渲染问题



首先,我对我的英语技能感到非常抱歉。

我目前正在通过dotnetcore3.1blazor开发一个网络项目。

在下面的源代码中,我使用IJSRuntime来调用一个需要很长时间的Javascript函数。

[Inject]
IJSRuntime JSRuntime { get; set; }
private async Task BtnDisplay()
await JSRuntime.InvokeVoidAsync("RefreshWebJS", Data);
}

Javascript函数需要很长时间,所以我添加了下面的源代码来添加一个微调器。

private async Task BtnDisplay()
{
showLoadingImg = true; // add
await JSRuntime.InvokeVoidAsync("RefreshWebJS", Data);
showLoadingImg = false;
}

剃刀页面上的微调器定义如下:

@if (showLoadingImg == true)
{
<div style="position: absolute; top: 0px; left: 0px; width: 100%; height: 100%; text-align: center;">
<img src="/images/LoadingImg.gif" style="position: absolute; top: 50%; left: 50%;" />
</div>
}

"StateHasChanged(("或";await InvokeAsync(((=>StateHasChanged(((";也不起作用。

当我使用Task而不是JSRuntime时,它工作得很好。

await Task.Delay(1000); 

为什么当我使用JSRuntime.InvokeVoidSync时它不起作用?

谢谢你,很抱歉你读到了难听的英语。

private async Task BtnDisplay()
{
showLoadingImg = true; // add
await Task.Delay(1);
await JSRuntime.InvokeVoidAsync("RefreshWebJS", Data);
showLoadingImg = false;
}

Blazor在异步任务中await的第一个Task完成时自动重新渲染。

因此,如果第一个Task是一个长时间运行的进程,那么在它完成之前,它不会重新渲染。

添加await Task.Delay(1)是允许在长时间运行的进程之前进行渲染的一种简单方法。

进一步阅读:https://github.com/dotnet/aspnetcore/issues/22159

这是Blazor工作方式的已知特征,Blazor的创建者也在该线程中推荐了这种方法(尽管他更喜欢await Task.Yield()——我总是忘记使用它!(

如前所述,还有一种使用同步事件处理程序的方法,它在新任务中启动JS Interop,然后立即返回。您必须确保在这个新任务完成后,使用await InvokeAsync(StateHasChanged):重新同步它

private bool ShowLoading = false;
private void HandleButtonClick()
{
ShowLoading = true;
Task.Run(async () => await CallLongRunningJs())
.ContinueWith(t => { ShowLoading = false; InvokeAsync(StateHasChanged); });
}
private async Task CallLongRunningJs()
{
await jsRuntime.InvokeVoidAsync("longRunningJsFunc", "data...");
}

它比Magoo先生提出的Task.Yield()方法更详细,但为了完整性,我认为在这里提到这一点是很好的。

相关内容

  • 没有找到相关文章

最新更新