在 Blazor 中,当同一自定义组件(如 )被多次渲染于同一页面时,需确保各实例状态隔离、互不干扰,并能将各自输入结果准确回传至父组件——通过 @bind-Value 双向绑定配合 EventCallback 即可优雅实现。
在 blazor 中,当同一自定义组件(如 `
要让多个
以下是改造后的 TextArea.razor 完整代码(含 JS 交互兼容性):
@inject IJSRuntime JsRuntime
@inject NavigationManager NavManager
<table width="100%">
<tr>
<td>
<table width="100%">
<tr>
<td>
<button @onclick="MakeBold">put bold</button>
</td>
</tr>
</table>
</td>
</tr>
<tr>
<td>
<textarea class="custom-textarea"
@bind="result"
placeholder="Deutsche Beschreibung"
rows="5"></textarea>
</td>
</tr>
</table>
<button @onclick="FinishAsync">finish</button>
@code {
[Parameter] public required string Value { get; set; }
[Parameter] public required EventCallback<string> ValueChanged { get; set; }
private string result = "";
protected override void OnInitialized()
{
// 初始化时同步外部传入的 Value 到内部状态
result = Value;
}
private async void MakeBold()
{
// 示例:调用 JS 实现富文本加粗(需配套 JS 函数)
await JsRuntime.InvokeVoidAsync("makeBold", "custom-textarea");
}
private async Task FinishAsync()
{
// 将当前 textarea 内容提交给父组件
await ValueChanged.InvokeAsync(result);
}
// 支持双向绑定的 setter(自动触发更新)
private string Result
{
get => result;
set
{
if (result != value)
{
result = value;
_ = ValueChanged.InvokeAsync(result); // 可选:实时同步(非必须)
}
}
}
}✅ 重要说明:
- 使用 @bind="result" 是为了本地编辑体验;但真正驱动父子通信的是 ValueChanged 回调。
- OnInitialized() 中初始化 result = Value 确保组件首次渲染时显示正确值。
- 若需实时响应输入(而非仅点击 finish),可将 @bind="Result" 并移除 FinishAsync 的手动调用,改用属性 setter 自动触发回调(见上方 Result 属性示例)。
在父组件中,只需为每个实例声明独立字段,并使用 @bind-Value 语法即可完成双向绑定:
<TextArea @bind-Value="Value1" />
<TextArea @bind-Value="Value2" />
<TextArea @bind-Value="Value3" />
<div class="mt-4">
<h5>Current values:</h5>
<ul>
<li>Field 1: "@Value1"</li>
<li>Field 2: "@Value2"</li>
<li>Field 3: "@Value3"</li>
</ul>
</div>
@code {
private string Value1 { get; set; } = string.Empty;
private string Value2 { get; set; } = string.Empty;
private string Value3 { get; set; } = string.Empty;
}? 最佳实践提示:
- 避免在子组件中直接操作 DOM ID(如 "custom-textarea"),多个实例会导致 ID 重复;建议结合 @ref 或生成唯一 ID(如 id="@($"textarea-{Guid.NewGuid()}")")提升健壮性;
- 如需统一处理多个字段提交逻辑,可在父组件中封装一个 SubmitAll() 方法,集中校验并提交 Value1/Value2/Value3;
- 若组件逻辑复杂,推荐进一步封装为 InputTextArea 并继承 InputBase
,以原生支持 EditContext 和表单验证。
通过该模式,你不仅解决了多实例状态隔离问题,还构建了可复用、可测试、符合 Blazor 数据流规范的组件体系。

















