eventcallback 是 blazor 中唯一推荐的跨组件通信机制,本质是带异步支持且具备生命周期防护的委托封装;它确保 ui 更新在正确渲染上下文中执行,避免 objectdisposedexception 和重绘失效问题。

EventCallback 是什么,为什么不能直接用 Action
Blazor 中子组件通知父组件,EventCallback 不是可选方案,而是唯一推荐的跨组件通信机制。它本质是带异步支持的委托封装,能确保 UI 更新在正确渲染上下文中执行;而裸 Action 或 Func 会绕过 Blazor 的渲染调度,导致状态变更不触发重绘,或引发“Cannot access a disposed object”错误。
常见错误现象:System.ObjectDisposedException: Cannot access a disposed object,多出现在子组件已卸载但回调仍被调用时——EventCallback 内部做了生命周期防护,Action 没有。
子组件定义 EventCallback 参数并触发
子组件需声明一个 EventCallback 类型的 [Parameter],类型与要传递的数据匹配(如 EventCallback<string></string>、EventCallback 表示无参)。触发时必须用 InvokeAsync,不能直接调用。
示例(子组件 Child.razor):
@code {
[Parameter] public EventCallback<string> OnNameSubmitted { get; set; }
private string inputName = "";
private async Task HandleSubmit()
{
await OnNameSubmitted.InvokeAsync(inputName); // 必须用 InvokeAsync
inputName = "";
}
}
- 参数名建议以
OnXxx开头,符合事件命名习惯 - 如果父组件未设置该回调,
InvokeAsync仍安全,不会抛异常 - 避免在
OnInitialized等生命周期中提前触发,此时父组件可能还未完成参数绑定
父组件接收并绑定 EventCallback
父组件在引用子组件时,用 @onxxx 语法(如 @onsubmit)或显式赋值方式绑定回调。Blazor 会自动将方法签名匹配为 EventCallback。
示例(父组件):
<Child OnNameSubmitted="HandleNameFromChild" />
@code {
private void HandleNameFromChild(string name)
{
Console.WriteLine($"Received: {name}");
// 此处修改父组件状态,会触发重渲染
Message = $"Hello, {name}!";
}
}
- 绑定方法可以是
void或Task,Blazor 会自动适配 - 若回调中需更新父组件状态(如
Message),无需手动调用StateHasChanged(),InvokeAsync已触发渲染队列 - 不要写成
@onnamesubmitted="HandleNameFromChild"—— 属性名大小写必须完全匹配子组件定义的参数名
传复杂对象或多个参数的处理方式
EventCallback 只支持单个参数,传多个值需封装为 record、class 或 ValueTuple。推荐用 record,轻量且不可变,避免子组件意外修改父组件数据。
示例:
public record SubmitData(string Name, int Age, bool IsSubscribed);
// 子组件
[Parameter] public EventCallback<SubmitData> OnFormSubmitted { get; set; }
// 触发
await OnFormSubmitted.InvokeAsync(new SubmitData(name, age, isChecked));
// 父组件
private void HandleForm(SubmitData data)
{
Console.WriteLine($"{data.Name}, {data.Age}");
}
- 避免用
dynamic或object,失去编译时检查和 IDE 支持 - 如果只是需要通知“发生了某事”而无需数据,用
EventCallback(无泛型)即可 - 注意 record 的默认相等性比较可能影响调试输出,但不影响回调逻辑
await,或者父组件绑定时拼错参数名——这两个地方一出错,回调静默失败,控制台也无提示。










