Blazor 的參數基本上可以分為事件外拋和傳值進去,但有時候會希望子元件能去執行母元件的某個方法,這個時候可以使用 c# 的 Delegate 的行為來實作。
使用 Event
一般的情況下,會將 Parameter 宣告為 EventCallback 來作為跟外面元件做溝通
Parent compoennt
1 2 3 4 5 6 7 8 9 10 11 12
| <div> <Child count="@count" countChange="@OnChange"/> </div>
@code { private int count; private void OnChange(int val) { count = val; } }
|
Child component
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| <div> <span>@count</span> <button @onclick="@OnClick"> click me </button> </div>
@code { [Parameter] public int count { get; set; } [Parameter] public EventCallback<int> countChange { get; set; } private async Task OnClick() { await countChange.InvokeAsync(count+1); } }
|
使用 Delegate
如果希望把一些運算是由母元件來決定,子元件只管畫面和基本的行為,那就可以使用 Delegate 的做法。
以上面的例子來說,將 count 的計算交給外面,裡面只做顯示數字和按鈕的事件。
子元件
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| <div> <span>@count</span> <button @onclick="@OnClick"> click me </button> </div>
@code { [Parameter] public int count { get; set; } [Parameter] public Func<int, int> countChange { get; set; } private async Task OnClick() { var result = countChange(count); Console.WriteLine($"parameter count: {count}, result {result}"); } }
|
母元件
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| <div> <Child count="@count" countChange="@OnChange"/> </div>
@code { private int count; private int OnChange(int val) { count = val + 1; StateHasChanged(); return count; } }
|
這邊要注意 StateHasChanged
,才能讓 blazor 重新 render 子元件。
根據這樣的修改,也就是說,可以讓把相同畫面的功能抽成元件,細節都交給外面,像是下面一次 +2
的功能。
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| <div> <Child count="@count" countChange="@OnChange"/> </div>
@code { private int count; private int OnChange(int val) { count = val + 2; StateHasChanged(); return count; } }
|
也許你會問那有機會用到 Action<>
嗎? 個人認為不太可能,因為 Action 是沒有回傳值,依照這種情境就直接用 EventCallback
更好。