Blazor WebAssembly 动态生成带展开/隐藏按钮的HTML列表失效问题求解
问题根因
你当前写法的核心问题是showFullDetails变量是在foreach循环内部声明的局部变量,Blazor每次触发组件重渲染时,都会重新执行整个foreach遍历逻辑,该变量会被重置为初始值false,所以点击后看不到预期的展开/折叠效果。
解决方案1:修改Person实体类存储状态(最简洁)
给你的Person类新增一个扩展属性存储展开状态:
public class Person { // 原有属性保持不变 public int Id { get; set; } public string FirstName { get; set; } public string LastName { get; set; } public int Age { get; set; } public string Email { get; set; } // 新增展开状态属性 public bool IsExpanded { get; set; } }
修改Razor代码如下:
@foreach (Person person in people) { <div class="card" @key="person.Id"> <div class="card-body"> <span @onclick="()=> person.IsExpanded = !person.IsExpanded" class="@(person.IsExpanded ? "oi oi-chevron-down" : "oi oi-chevron-right")"></span> <span>@person.Type.TypeName</span> <span>@person.FirstName @person.LastName</span> @if (person.IsExpanded) { <div>@person.Age - @person.Email</div> } </div> </div> }
解决方案2:用字典存储状态(无需修改实体类)
如果不能修改Person类的定义,可以在组件内用字典单独存储每个人员的展开状态:
// 在组件@code块中声明字典 private Dictionary<int, bool> _expandStateDict = new(); // 在人员数据加载完成后初始化字典 protected override void OnInitialized() { foreach(var p in people) { _expandStateDict.TryAdd(p.Id, false); } }
修改Razor代码如下:
@foreach (Person person in people) { <div class="card" @key="person.Id"> <div class="card-body"> <span @onclick="()=> _expandStateDict[person.Id] = !_expandStateDict[person.Id]" class="@(_expandStateDict[person.Id] ? "oi oi-chevron-down" : "oi oi-chevron-right")"></span> <span>@person.Type.TypeName</span> <span>@person.FirstName @person.LastName</span> @if (_expandStateDict[person.Id]) { <div>@person.Age - @person.Email</div> } </div> </div> }
补充说明
两种方案都给循环元素加了@key特性,可以避免Blazor在做虚拟DOM diff时出现匹配错误,是动态渲染列表的最佳实践。
内容的提问来源于stack exchange,提问作者Jake
相关产品推荐
相关产品推荐

