今天要來正式介紹客製化元件了,說是客製化元件,其實也就是釐清元件之間的相處模式,父元件與子元件如何溝通的問題。在開發階段的時候,往往都會發現一個元件的某個部分,與另一個元件的某個部分高度重疊,此時當某一處需要調整時,可能也會需要同步修改另一處,那麼將重複的部份抽成共用元件就會變得很簡單。


客製化元件,就像前面說的有共用的時候抽出會讓之後維護變得很簡單,但不是一定要有重複內容才能做切割,如果一個畫面太過龐大,也是可以考慮切成一小塊一小塊來拼湊畫面,在畫面調整時能快速掌握目標,就好比把一大串的複雜方法,切成一個一個單元方法,只是目標變成了畫面元件,所以心法不變,只是樣子改變,那我們就開始吧!

父子元件溝通問題說穿了就只需要做兩件事情,傳入參數與傳出事件,父元件透過傳入參數來設定子元件,子元件傳出事件通知父元件使用者事件產生。

  1. 傳入參數

想要接收父元件的參數只需要在欄位或屬性上加 [Parameter] 屬性即可,如:

1
2
[Parameter]
public int Year { get; set; }

而父元件只需要透過 {PARAMETER NAME}="value" 即可繫結,如:

1
<Child Year="2020" />

就是這麼簡單。

  1. 傳出事件

如果傳入參數需要通知父元件異動情況時,可以為該參數增加一個事件回呼參數如:

1
2
3
4
5
[Parameter]
public int Year { get; set; }

[Parameter]
public EventCallback<int> YearChanged { get; set; }

並且綁定事件:

1
2
3
4
5
6
7
8
9
10
<Child Year="year" YearChanged="YearChanged" />

@code {
private int year = 1979;

private void YearChange(int value)
{
year = value;
}
}

這樣就可以捕捉異動內容、修改變數,然後重新傳給子元件,但如果每個簡單情境都需要這樣做,是不是就很麻煩?

此時就可以使用 @bind-{PARAMETER NAME}來綁定參數如:

1
<Child @bind-Year="year" />

這會幫我們綁定 YearYearChanged 了,但該事件回呼參數名稱一定要是該參數名稱並後綴 Changed{PARAMETER NAME}Changed,不然是沒有辦法使用的唷!

而子元件的事件不一定都是由參數產生,可能是某些行為需要通知父元件,那我們可以額外新增 EventCallback<T> 事件回呼參數,並透過 InvokeAsync() 傳入內容即可,如:

1
2
3
4
5
6
7
[Parameter]
public EventCallback<int> ChildOnInit { get; set; }

protected override async Task OnInitializedAsync()
{
await ChildOnInit.InvokeAsync(0);
}

這樣一來子元件完成初始化後,就會透過 ChildOnInit 傳遞一個 0 數字出去,此時父元件就可以透過回呼函式來處理子元件初始化後的行為,如:

1
2
3
4
5
6
7
<Child ChildOnInit="ChildOnInit" ></Child>
@code {
private void ChildOnInit(int value)
{
Console.WriteLine(value);
}
}

以上就是客製化元件時,怎麼處理父子溝通問題,然而客製化元件也不一定要有傳入參數,有時候可能只是 UI 層面的重複,不一定有邏輯產生,也是可以抽出來唷。

感謝大家的閱讀,我們明天見。

參考資料
使用元件參數的父系對子系結
事件回呼