Blazor使用Timer切换组件显隐异常问题排查
问题解决:Blazor后台Timer无法切换自定义组件显示状态
核心问题
你的代码中,父组件虽然更新了showHelloWorld1和showHelloWorld2变量,但没有将这些变量绑定到子组件的对应参数上,导致子组件无法感知状态变化;另外子组件的参数命名不符合Blazor的规范约定。
修复步骤
- 绑定子组件参数:在父组件的子组件标签上,通过属性绑定将父组件的状态变量传递给子组件的参数。
- 修正参数命名规范:Blazor组件参数推荐使用PascalCase(大驼峰)命名,避免潜在的绑定问题。
- 移除不必要的组件引用:若无需直接调用子组件方法,
@ref可以删除,简化代码。
修改后的完整代码
Index.razor
@page "/index" @implements IDisposable <h3>Background Timer Example</h3> @if (showComponent) { <div class="alert alert-success" role="alert"> This is a visible component! </div> } <!-- 绑定子组件参数 --> <HelloWorld1 ShowHelloWorld1="@showHelloWorld1" /> <HelloWorld2 ShowHelloWorld2="@showHelloWorld2" /> <button class="btn btn-primary" @onclick="ToggleComponent">Toggle Component</button> @code { private bool showComponent = true; private bool showHelloWorld1 = true; private bool showHelloWorld2 = true; private const int TimerInterval = 3000; private System.Threading.Timer timer; protected override void OnInitialized() { timer = new System.Threading.Timer(ToggleComponentVisibility, null, TimerInterval, TimerInterval); } private async void ToggleComponentVisibility(object state) { showComponent = !showComponent; showHelloWorld1 = !showComponent; showHelloWorld2 = !showComponent; await InvokeAsync(StateHasChanged); } private async Task ToggleComponent() { showComponent = !showComponent; showHelloWorld1 = !showComponent; showHelloWorld2 = !showComponent; await InvokeAsync(StateHasChanged); } public void Dispose() { timer?.Dispose(); } }
HelloWorld1.razor
<h4>Hello from HelloWorld1!</h4> @if (!ShowHelloWorld1) { <p>Hidden!</p> } else { <p>Visible!</p> } @code { // 修改为PascalCase命名的参数 [Parameter] public bool ShowHelloWorld1 { get; set; } }
HelloWorld2.razor
<h4>Hello from HelloWorld2!</h4> @if (!ShowHelloWorld2) { <p>Hidden!</p> } else { <p>Visible!</p> } @code { // 修改为PascalCase命名的参数 [Parameter] public bool ShowHelloWorld2 { get; set; } }
说明
- 父组件通过
ShowHelloWorld1="@showHelloWorld1"将状态变量绑定到子组件参数,当父组件更新showHelloWorld1时,子组件会自动接收新值并重新渲染。 InvokeAsync(StateHasChanged)确保在Timer的后台线程中安全触发组件状态更新,这部分你的代码是正确的。- 实现
IDisposable接口并添加@implements IDisposable是更规范的做法,确保Timer被正确释放。
内容的提问来源于stack exchange,提问作者Max
相关产品推荐
相关产品推荐

