父子組件傳值
在 Blazor
中,組件之間的通信可以通過 [Parameter]
參數和 EventCallback<T>
事件回調實現。下面分別給出 父組件傳遞值給子組件 和 子組件傳遞值給父組件 的簡單示例。
1.1 父組件傳遞值給子組件
步驟:
- 在子組件中定義
public
屬性,并使用[Parameter]
特性標記。 - 在父組件中通過綁定屬性將值傳遞給子組件。
示例代碼:
子組件 ChildComponent.razor
<h3>子組件收到的值: @Message</h3>@code {[Parameter]public string Message { get; set; }
}
父組件 ParentComponent.razor
<ChildComponent Message="@message" />@code {private string message = "Hello from parent!";
}
1.2 子組件傳遞值給父組件
步驟:
- 使用
EventCallback<T>
實現子組件向父組件傳值。 - 子組件觸發事件并攜帶數據,父組件監聽該事件并處理數據。
示例代碼:
子組件 ChildComponent.razor
<button @onclick="SendMessage">發送消息給父組件</button>@code {[Parameter]public EventCallback<string> OnMessageSent { get; set; }private async Task SendMessage(){await OnMessageSent.InvokeAsync("這是來自子組件的消息");}
}
父組件 ParentComponent.razor
<ChildComponent OnMessageSent="HandleMessage" />
<p>收到子組件的消息: @receivedMessage</p>@code {private string receivedMessage;private void HandleMessage(string message){receivedMessage = message;}
}
1.3 總結
通信方向 | 實現方式 |
---|---|
父組件 → 子組件 | 使用 [Parameter] 傳遞屬性值 |
子組件 → 父組件 | 使用 EventCallback<T> 觸發事件 |
這種方式可以滿足大多數 Blazor
組件間的基本通信需求。
級聯組件傳值
在 Blazor
中,級聯傳值(Cascading Communication) 可以通過以下幾種方式實現:
- 使用
CascadingParameter
實現層級組件傳值 - 使用
CascadingValue
組件包裹子樹,并向下傳遞數據
下面是一個 三層級組件傳值的完整示例(父 → 子 → 孫)。
2.1 使用 CascadingValue
和 CascadingParameter
示例結構
ParentComponent.razor
└── ChildComponent.razor└── GrandChildComponent.razor
Ⅰ. 父組件:ParentComponent.razor
@page "/parent"<CascadingValue Value="@message"><ChildComponent />
</CascadingValue>@code {private string message = "來自父組件的消息";
}
Ⅱ. 子組件:ChildComponent.razor
<h4>子組件收到消息: @cascadeMessage</h4>
<GrandChildComponent />@code {[CascadingParameter]public string cascadeMessage { get; set; }
}
Ⅲ. 孫組件:GrandChildComponent.razor
<h5>孫組件收到消息: @cascadeMessage</h5>@code {[CascadingParameter]public string cascadeMessage { get; set; }
}
2.2 運行效果
訪問 /parent
路由后,頁面將顯示如下內容:
子組件收到消息: 來自父組件的消息
孫組件收到消息: 來自父組件的消息
說明:
CascadingValue
將值從父組件廣播給其所有嵌套子組件。- 所有子組件通過
[CascadingParameter]
接收值,無需手動逐層傳遞。
2.3 注意事項
注意點 | 說明 |
---|---|
類型匹配 | CascadingValue 的類型必須與接收組件的 CascadingParameter 類型一致 |
多個值 | 可以使用多個 CascadingValue 包裹不同值,或使用對象封裝多個字段 |
性能影響 | 不建議過度使用級聯參數,避免造成上下文污染和性能問題 |
2.4 進階用法:傳遞對象而非基本類型
<CascadingValue Value="@userContext"><ChildComponent />
</CascadingValue>@code {private UserContext userContext = new UserContext { Name = "Alice", Role = "Admin" };
}public class UserContext {public string Name { get; set; }public string Role { get; set; }
}
子組件中接收:
[CascadingParameter]
public UserContext userContext { get; set; }
如需更復雜的通信(如跨層級雙向綁定),可以結合 EventCallback
或使用狀態管理庫(如 Fluxor
)。
更復雜的通信
在 Blazor
中,當組件層級較深或需要實現 跨層級雙向綁定通信 時,推薦使用以下兩種方式:
? 方案一:結合 EventCallback
實現跨層級通信
場景說明:
- 組件層級嵌套較深(如
父 → 子 → 孫
)。 - 需要從最內層子組件向頂層組件傳遞數據,并同步更新狀態。
示例結構:
ParentComponent.razor
└── ChildComponent.razor└── GrandChildComponent.razor
1. 父組件:ParentComponent.razor
@page "/parent"<h3>父組件顯示的值: @sharedValue</h3><ChildComponent OnValueChanged="UpdateValue" />@code {private string sharedValue = "初始值";private void UpdateValue(string newValue){sharedValue = newValue;}
}
2. 子組件:ChildComponent.razor
<GrandChildComponent OnValueChanged="OnValueChanged" />@code {[Parameter]public EventCallback<string> OnValueChanged { get; set; }
}
3. 孫組件:GrandChildComponent.razor
<input @bind="inputValue" />
<button @onclick="SendValueToParent">發送到父組件</button>@code {private string inputValue = "默認輸入";[Parameter]public EventCallback<string> OnValueChanged { get; set; }private async Task SendValueToParent(){await OnValueChanged.InvokeAsync(inputValue);}
}
運行效果:
- 在孫組件中修改輸入框內容并點擊按鈕;
- 消息會逐級上傳至父組件;
- 父組件中的
sharedValue
被更新并重新渲染。
? 方案二:使用狀態管理庫 Fluxor 實現全局共享狀態(推薦)
優勢:
- 避免層層傳遞參數和事件回調;
- 實現組件間真正的“雙向綁定”;
- 支持集中管理應用狀態,提升可維護性。
安裝 Fluxor
通過 NuGet 安裝:
dotnet add package Fluxor --version 6.6.0
注冊服務(在 Program.cs
中):
builder.Services.AddFluxor(options =>options.ScanAssemblies(typeof(Program).Assembly));
1. 創建 State 類:CounterState.cs
public class CounterState(int count)
{public int Count { get; } = count;
}
2. 創建 Feature 和 Reducer:CounterFeature.cs
public class CounterFeature : Feature<CounterState>
{public override string GetName() => "Counter";public override CounterState GetInitialState() => new(0);
}public record IncrementAction();
public record DecrementAction();public class CounterReducer
{[ReducerMethod]public static CounterState Increment(CounterState state, IncrementAction action) =>new(state.Count + 1);[ReducerMethod]public static CounterState Decrement(CounterState state, DecrementAction action) =>new(state.Count - 1);
}
3. 創建 Store 并使用(任意組件中)
使用 Store 的組件示例:CounterComponent.razor
@inject IStore store;
@inject IDispatcher dispatcher;<p>當前計數: @counterState.Value.Count</p>
<button @onclick="Increment">+1</button>
<button @onclick="Decrement">-1</button>@code {private IState<CounterState> counterState;protected override void OnInitialized(){counterState = store.GetState<CounterState>();}private void Increment() => dispatcher.Dispatch(new IncrementAction());private void Decrement() => dispatcher.Dispatch(new DecrementAction());
}
運行效果:
- 多個組件都可以訪問和修改同一個
Count
值; - 所有監聽該狀態的組件都會自動刷新;
- 實現了真正的跨層級、雙向綁定通信。
🧠 總結對比
方式 | 適用場景 | 優點 | 缺點 |
---|---|---|---|
EventCallback | 層級不深 / 單向/雙向傳值 | 簡單直接 | 層級多時繁瑣 |
CascadingParameter | 同一樹狀結構下傳值 | 快速廣播 | 只能讀取,不能雙向綁定 |
Fluxor | 全局狀態共享 / 復雜交互 | 狀態統一管理,解耦組件 | 初期配置復雜 |
? 推薦實踐
- 小型項目:使用
EventCallback
&CascadingParameter
。 - 中大型項目或需要跨組件共享狀態:優先使用
Fluxor
。 - 更高級需求可考慮配合
TimeWarp.State
或MediatR
。
說明:
- Blazor-State 已更名為 TimeWarp.State
相關 nuget
包資源:
Blazor-State
,https://www.nuget.org/packages/Blazor-State/11.0.0-beta.36
TimeWarp.State
,https://www.nuget.org/packages/TimeWarp.State/
MediatR
,https://www.nuget.org/packages/MediatR