Blazor WebAssembly 5循环渲染组件时实现单选并取消其余选中的方法
实现方案
核心逻辑是把选中状态的管控权统一交给父组件维护,子组件仅作为纯展示组件接收参数、触发点击回调即可,不需要自行维护选中状态,这是Blazor中同组单选类交互的最优实践。
1. 修正PersonItem.Razor
首先修复原有代码的参数定义错误,同时删除子组件内部修改IsSelected参数的逻辑(Blazor中不推荐子组件自行修改来自父级的Parameter参数,会导致状态不同步):
@if (Person!= null) { <div @onclick="InvokeOnClick" style="@GetStyle()">@Person.Name</div> } @code { // 修复原有参数名的拼写错误 [Parameter] public Person Person { get; set; } = null; [Parameter] public bool IsSelected { get; set; } = false; [Parameter] public EventCallback<Person> OnClick { get; set; } private string GetStyle() => IsSelected ? "cursor:default;color:blue" : "cursor:pointer"; private async Task InvokeOnClick() { // 移除子组件内部修改IsSelected的逻辑,完全由父级传参控制 await OnClick.InvokeAsync(Person); } }
多余的OnParametersSetAsync方法可以直接删掉,不需要手动调用StateHasChanged,父级参数更新时组件会自动重渲染。
2. 修正MyPage.razor
父组件新增字段存储当前选中的Person实例,遍历渲染时给每个子组件传递对应的IsSelected状态,同时接收子组件的点击回调更新选中值:
@inject IPersonRepo personRepo; @if (PersonList != null) { foreach (var person in PersonList) { <PersonItem Person="@person" IsSelected="@(person == SelectedPerson)" OnClick="@OnPersonSelected"> </PersonItem> } } else { <div>Not Yet!</div> } @code { public List<Person>? PersonList { get; set; } = null; // 新增字段维护当前选中的Person public Person? SelectedPerson { get; set; } protected async override Task OnInitializedAsync() { await GetAllPersons(null); await base.OnInitializedAsync(); } public async Task GetAllPersons(EventArgs e) { PersonList = await personRepo.GetAllPersons(); } // 子组件点击回调,更新当前选中值 private void OnPersonSelected(Person selected) { SelectedPerson = selected; } }
实现效果:每次点击任意PersonItem,都会触发父组件更新SelectedPerson的值,所有子组件的IsSelected参数会自动重新和当前SelectedPerson比对,只有匹配的项会是选中状态,其余项自动取消选中,不需要手动遍历所有项修改状态,性能和可维护性都是最优的。
内容的提问来源于stack exchange,提问作者theGhostN
相关产品推荐
相关产品推荐

