假如我們想增加的按鈕用來清除 form(表單)的資料,最快的方式是增加一個 type="reset" 的按鈕,這時候就用到兩個按鈕了,可以用到 Blazor 的核心概念:元件封裝。
我們先在 Shared 資料夾新增一個 Razor 元件名為 MyButton,定義 3 個變數分別代表按鈕類型、按鈕樣式、按鈕名稱,注意要在屬性上面加上 [Parameter],這是告訴 Blazor 這些屬性的值來自呼叫這個元件的父元件。

接著移除標題的單向繫結,再將更新時間的 div 移到 <EditForm> 外面,因為 reset 按鈕會清除整個 form,我們不希望更新時間也被清除。最後在最下面使用兩個 <MyButton> 元件,再輸入我們要的按鈕類型、按鈕樣式、按鈕名稱,這邊 Blazor 會告訴你還有哪些 Parameter 沒有被使用,如果有重複的 Parameter 也會有提示,所以不用擔心。

按下 Reset 按鈕,可以看到標題跟內容都被清除了。

要注意的是 Parameter 不支援混合 razor 及 html 字串的寫法,如果想這麼做建議用 field、property 或是 string 方法回呼組合好的字串。


Parameter 還有一點要避免,當父元件傳值到子元件時,父元件若有 StateHasChanged 相關動作,會將父元件及子元件重新渲染,除非在子元件用一個變數保存父元件傳來的值。
上面的文字說明似乎沒看懂,我們來看微軟給的例子,先建立一個擴充元件,裡面做的事情很簡單,只要點擊 <div> 就會收縮或是展開內容。還有一個類型為 RenderFragment 的 ChildContent,這是讓使用該元件的外部元件決定內容範本。

接著在 Post.razor 呼叫兩個 Expander,第一個有用到 ChildContent 並放入 <p> 元素,最後看到一個 button 帶有 @onclick="StateHasChanged" 的事件,模擬父元件的 StateHasChanged 事件。

開啟網頁可以看到兩個 Expander 的 Expanded 皆為 True

接著兩個 Expander 都點一下,可以看到 Expanded 都變 False 了

不過如果這時候點底下的 button,會發現只有上面的 Expanded 變成 True,這是為什麼?

原因就在於父元件的狀態(state)跟 ChildContent 這個屬性,因為父元件的 state 改變了會重新渲染(render)並將新資料傳給第一個 Child,所以 Expanded 被重設為 true,第二個 Child 因為沒有接收 ChildContent 所以不會重新渲染。
為了避免這問題,可以定義一個私用欄位(field)名為 _expanded,當元件初始化時儲存父元件傳來的 Expanded,之後的邏輯都根據 _expanded 處理。

引用:
注:本文程式碼透過 .NET 6 + Visual Studio 2022 重構,可點選原文連結與重構後程式碼比較學習,謝謝閱讀,支援原作者