如何解决使用 IJSRuntime Blazor 时的屏幕渲染问题
首先,我对我的英语水平感到非常抱歉。
我目前正在通过 dotnet core 3.1 blazor 开发一个 Web 项目。
在下面的源代码中,我使用 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.InvokeVoidAsync 时它不起作用?
感谢您阅读困难的英语。
解决方法
private async Task BtnDisplay()
{
showLoadingImg = true; // add
await Task.Delay(1);
await JSRuntime.InvokeVoidAsync("RefreshWebJS",Data);
showLoadingImg = false;
}
Blazor 在异步任务中的第一个 Task
完成后自动重新渲染。
因此,如果第一个 await
是您长时间运行的进程,则在完成之前它不会重新渲染。
添加 Task
是一种允许在长时间运行的进程之前进行渲染的简单方法。
进一步阅读:https://github.com/dotnet/aspnetcore/issues/22159
这是 Blazor 工作方式的已知特性,Blazor 的创建者也在该线程中推荐了这种方法(尽管他更喜欢 await Task.Delay(1)
- 我总是忘记使用它!)
正如之前的评论中提到的,还有一种同步事件处理程序的方法,它在一个新任务中启动 JS Interop 并在此之后立即返回。您必须确保在完成此新任务后重新同步,使用 import cats.effect.IO
import fs2.Stream
val s = Stream(1,2,3,4,1,2).covary[IO]
val grouped: Stream[IO,Stream[IO,Int]] = s.groupAdjacentBy(x => x == 1)
.chunkN(2,allowFewer = true)
.map(ch => Stream.fromIterator[IO](ch.flatMap(_._2).iterator))
val result: Stream[IO,IO[Int]] = for {
group <- grouped
element = group.compile.foldMonoid
} yield element
assertEquals(result.map(_.unsafeRunSync()).compile.toList.unsafeRunSync(),List(10,9,5))
:
await InvokeAsync(StateHasChanged)
它比 Magoo 先生提出的使用 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...");
}
的方法更冗长,但我认为为了完整起见,在这里提及这一点很好。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。