如何使用string.Format处理Blazor中的@ref以简化下拉项代码
问题
我有大量重复的Blazor下拉项代码,示例如下:
@if (ItemTest.Contains("One")) { <li class="dropdown-item"> <button @ref="_btn1" class="item" id="0" @onclick=Open1>One</button> </li> <li class="dropdown-item"> <button @ref="_btn2" class="item" id="1" @onclick=Open2>Two</button> </li> } @if (ItemTest.Contains("Two")) { <li class="dropdown-item"> <button @ref="_btn3" class="item" id="3" @onclick=Open3>Three</button> </li> }
我想重写代码以减少行数,提升可读性和可维护性,请问如何用string.Format来处理@ref?
解答
首先要明确:Blazor的@ref是编译时指令,无法通过string.Format这类字符串拼接方式动态生成——因为字符串渲染后仅为静态文本,Blazor不会解析其中的指令绑定。要优化这类重复代码,更合理的方案是通过「数据驱动+组件复用」实现:
步骤1:定义下拉项数据模型
把每个按钮的关键参数封装成类,统一管理配置:
public class DropdownItem { public string ShowKey { get; set; } // 用于判断是否显示的标识(对应原代码的"One"/"Two") public string DisplayText { get; set; } // 按钮显示文本 public string ButtonId { get; set; } // 按钮ID public Action ClickHandler { get; set; } // 点击事件逻辑 }
步骤2:初始化数据集合与引用存储容器
在组件代码块中,把所有下拉项的配置统一存入集合,同时用字典替代零散的_btn1/_btn2变量存储按钮引用:
private List<DropdownItem> _dropdownConfigs = new() { new DropdownItem { ShowKey = "One", DisplayText = "One", ButtonId = "0", ClickHandler = Open1 }, new DropdownItem { ShowKey = "One", DisplayText = "Two", ButtonId = "1", ClickHandler = Open2 }, new DropdownItem { ShowKey = "Two", DisplayText = "Three", ButtonId = "3", ClickHandler = Open3 }, }; private Dictionary<string, ElementReference> _buttonRefs = new();
步骤3:循环渲染下拉项
用循环替代重复的@if和HTML代码,通过字典绑定@ref:
@foreach (var item in _dropdownConfigs.Where(i => ItemTest.Contains(i.ShowKey))) { <li class="dropdown-item"> <button @ref="@(_buttonRefs[item.ButtonId])" class="item" id="@item.ButtonId" @onclick="item.ClickHandler"> @item.DisplayText </button> </li> }
为什么不推荐用string.Format?
string.Format生成的是HTML字符串,Blazor默认会转义特殊字符;即使强制渲染为HTML(@((MarkupString)formattedContent)),@ref也不会被Blazor识别,无法完成组件引用绑定。- 这种方式会丢失Blazor的类型安全和编译时检查,增加调试与维护难度。
额外优化:封装独立组件
如果这类下拉项在多个页面复用,可以进一步封装成组件,彻底消除重复代码:
<!-- DropdownItem.razor --> <li class="dropdown-item"> <button @ref="ButtonRef" class="item" id="@ButtonId" @onclick="ClickHandler">@DisplayText</button> </li> @code { [Parameter] public string ButtonId { get; set; } [Parameter] public string DisplayText { get; set; } [Parameter] public Action ClickHandler { get; set; } [Parameter] public ElementReference ButtonRef { get; set; } }
父组件中使用:
@foreach (var item in _dropdownConfigs.Where(i => ItemTest.Contains(i.ShowKey))) { <DropdownItem ButtonId="@item.ButtonId" DisplayText="@item.DisplayText" ClickHandler="@item.ClickHandler" ButtonRef="@(_buttonRefs[item.ButtonId])" /> }
内容的提问来源于stack exchange,提问作者Sarahrb
相关产品推荐
相关产品推荐

