Blazor父子组件通信依靠[Parameter]和EventCallback<T>机制实现单向数据流:父传子用[Parameter]接收参数,子传父用EventCallback<T>回调通知,二者配合确保数据流清晰可控、UI响应及时。

[Parameter] 和 EventCallback<T> 机制——用对了,父子数据流清晰可控;用错了,UI 不刷新、回调收不到、类型报错全是常态。
子组件收不到父组件传的值?检查 [Parameter] 是否漏写
这是最常踩的坑:父组件写了 <Child Title="Hello"></Child>,子组件里却只定义了 public string Title { get; set; } = "default";,没加 [Parameter] 特性。结果值永远是默认值,且修改父组件字段也不会触发子组件重绘。
-
[Parameter]是必须的标记,它告诉 Blazor:“这个属性由外部决定,要参与渲染生命周期” - 可选参数可以带默认值:
[Parameter] public string Title { get; set; } = "无标题"; - 必需参数建议不设默认值,让编译器或运行时尽早暴露缺失绑定(比如
[Parameter] public int Id { get; set; }) - 引用类型(如
List<string>、Dictionary<string, object>)传入后,子组件直接修改内容(如Items.Add("x"))不会触发父组件更新——因为没走参数重赋值流程,UI 也不会响应
子组件怎么把操作结果通知父组件?用 EventCallback<T> 而不是普通方法
子组件不能直接调用父组件的公开方法,也不能用 public Action<string> OnSubmit 这类裸委托——Blazor 会忽略它,且无法保证线程安全和 UI 刷新时机。
- 子组件必须声明:
[Parameter] public EventCallback<string> OnSubmit { get; set; } - 触发时必须用
await OnSubmit.InvokeAsync("data"),不能省略await,否则可能跳过渲染队列 - 调用前建议加守卫:
if (OnSubmit.HasDelegate) await OnSubmit.InvokeAsync(data);,避免空引用异常 - 父组件绑定时方法签名必须严格匹配泛型类型,比如子组件是
EventCallback<Book>,父组件 handler 就得是void Handle(Book b)或Task Handle(Book b),否则编译失败
@bind-Value 是怎么实现双向绑定的?别自己手写 Value/ValueChanged 配对
Blazor 的 @bind-Value 不是语法糖,而是框架自动识别命名约定后的智能绑定。你手动实现时若命名不规范,就会失效。
- 子组件必须同时提供两个属性:
[Parameter] public string Value { get; set; }和[Parameter] public EventCallback<string> ValueChanged { get; set; } - 属性名必须是
Value/ValueChanged(大小写敏感),不能是Text/TextChanged—— 否则@bind-Text="model"不生效 - 父组件使用
<MyInput @bind-Value="inputText" />,Blazor 会自动拆解为Value="@inputText"+ValueChanged="value => inputText = value" - 如果子组件内部需要校验再更新,应在
ValueChanged触发后、调用InvokeAsync前做判断,而不是在Value的 setter 里写逻辑(setter 可能被多次调用,且不保证顺序)
传复杂对象或一堆参数时,CaptureUnmatchedValues 怎么用才不翻车
当子组件需接收任意数量、动态名称的参数(比如封装第三方 UI 组件),可以用 [Parameter(CaptureUnmatchedValues = true)] 接收所有未显式声明的属性,但要注意类型和生命周期。
- 声明方式:
[Parameter(CaptureUnmatchedValues = true)] public Dictionary<string, object>? AdditionalAttributes { get; set; } - 它只捕获 HTML 属性(如
class、data-id)和未被其他[Parameter]匹配的 Razor 属性,不包括嵌套对象字段 - 不要在子组件里直接修改
AdditionalAttributes的内容(如AdditionalAttributes["class"] += " new"),因为它是父组件传来的引用,改了会影响父组件状态;应新建字典或用@attributes="AdditionalAttributes"直接透传给底层元素 - 配合
@attributes使用最安全:<div @attributes="AdditionalAttributes">...</div>,Blazor 会自动展开所有 key/value 为 HTML 属性
StateHasChanged() 显式调用或绑定链触发时刷新。所以看到值变了但界面没反应,先查是不是在子组件里绕过了参数机制直接改了内部字段,或者忘了 await EventCallback。


















