我正在制作一个 Blazor 服务器端项目,我想制作一个单击后停用的按钮,但不使用 disabled
的 <button>
属性。代码非常简单:
@functions {
LogInForm logInForm = new LogInForm();
bool IsDisabled;
SignInResult result;
protected override void OnInitialized()
{
IsDisabled = false;
}
async Task TryLogIn()
{
IsDisabled = true;
StateHasChanged();
result = await _LogInService.TryLogIn(logInForm);
Console.WriteLine("Logging status : " + (result.Succeeded ? "Sucess" : "Failure"));
IsDisabled = false;
StateHasChanged();
}
}
出于奇怪的原因,第一个
StateHasChanged
没有触发,但第二个确实重新呈现页面。通过进入 Debug模式并进入 StateHasChanged()
方法,它可以很容易地进行测试。第二次调用时,它会在进入方法后停止在 HTML 代码上,但不是第一次。为什么这样 ?
注意: 我不是在寻找任何仅使用
Task.Delay
或 Task.Run(...)
的解决方法,因为它在这些线程和 UI 刷新线程之间存在竞争条件,因此它不是一个可靠的解决方案。我正在寻找有关 StateHasChanged()
行为的答案或通过使用 PropertyChanged
或 EventCallback
等事件并将按钮作为子组件放置的解决方法。编辑: 经过一些测试,似乎
StateHasChanged()
仅在对 await
执行 Task
操作后才触发组件的重新渲染。可以通过在 result = await _LogInService.TryLogIn(logInForm);
行中添加注释或将 IsDisabled = ...
更改为 await new Task.Run(() => { IsDisabled = ...})
来轻松测试。我现在有一些解决方法,但我仍然想知道为什么这是一个功能。 StateHasChanged()
不应该在任何操作后重新渲染吗?或者它认为只有 async
操作(所以主要是服务器调用)可以改变 UI 中的某些内容? 最佳答案
以下是描述重新渲染如何发生的执行流程:
现在,当您在为局部变量 IsDisabled 赋值后调用 StateHasChanged 时,并没有真正改变组件的状态,并且没有理由调用 StateHasChanged 会产生重新渲染。当您调用 StateHasChanged 时,它只是将该组件的渲染请求排入队列。但是没有理由重新渲染......
操作的类型是否为异步无关,除了 OnInitializedAsync 方法,在这种情况下,当 OnInitializedAsync 方法完成时会自动调用 StateHasChanged 方法以再次重新渲染 UI,使用新数据由在 OnInitializedAsync 方法中执行的异步调用检索。
更新:
您可以通过多种方式完成您想要的操作,这里演示了最简单的方式:
<input type="button" value="Click me now" disabled="@IsDisabled" @onclick="TryLogIn" />
@code{
bool IsDisabled;
protected override void OnInitialized()
{
IsDisabled = false;
}
async Task TryLogIn()
{
IsDisabled = true;
// Do some async work here...
// Note: Replace your async method with Task.Delay
await Task.Delay(5000);
IsDisabled = false;
}
}
这应该工作...
注意:禁用按钮控件的唯一方法是使用 disabled 属性
无需调用 StateHasChanged 方法。当编译器(编译器)为您的组件创建一个 EventCallback 'delegate' 时,它会被编译器插入到您的源代码中的代码自动调用。
触发 UI 事件后会自动调用 StateHasChanged 方法。
关于c# - StateHasChanged() 重新渲染组件两次,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/58932854/