深入淺出Blazor webassembly之理解ChildContent RenderFragment
===========================================
參考
===========================================
https://blazor-university.com/templating-components-with-renderfragements/
https://docs.microsoft.com/en-us/aspnet/core/blazor/components/templated-components
===========================================
背景
===========================================
普通組件的使用示例, 注意僅僅包含組件的IncrementAmount 參數, 不能包含子html內容或子tag.
<Counter IncrementAmount="5"/>
Counter組件的定義代碼:
@page "/counter" <h1>Counter</h1> <p>Current count: @currentCount</p> <button class="btn btn-primary" @onclick="IncrementCount">Click me</button> @code { [Parameter] public int IncrementAmount{ get; set; } = 1; private int currentCount = 0; private void IncrementCount() { currentCount= currentCount+ IncrementAmount; } }
這樣的簡單組件, 在被使用時不允許添加inner html內容, 組件的html都由組件自身確定, 外界僅僅能輸入一些參數.
如果在使用這樣的組件時, 硬要加inner html, 運行時會報錯.
@page "/simplepage" <Counter IncrementAmount="5">something</Counter>

===========================================
帶 RenderFragment 的組件
===========================================
如果我們要讓 Counter 組件要對外開放html樣式控制, 比如 IncrementAmount <10, 用 h1 樣式; IncrementAmount <20 用h2 樣式; IncrementAmount <30 用h3 樣式; 上面實現方式的組件做起來就很不靈活了, 就非常不便.
Blazor提供一個好的解決方式是, 即帶有 RenderFragment 的組件. 需要說明的是, RenderFragment 類型實際上是一個delegate 代理, 以后再細講這個.
關于組件增加 RenderFragment 參數的規則是:
- (1)如果組件帶有inner html 就必須為組件增加 RenderFragment 參數.
- (2)如果使用組件時, inner html 是直接放到組件tag之下, 則組件一定要有 ChildContent RenderFragment 參數, 否則運行報錯.
- (3)如果使用組件時, inner html是放到某個自定義tag下, 則組件必須定義一個和tag同名的RenderFragment 參數 或 ChildContent RenderFragment 參數. Blazor 優先為同名的RenderFragment 參數賦值, 如果沒有的話, 會試圖為ChildContent參數賦值, 如果ChildContent參數也不存在的話, 就會運行報錯.
- (4)組件定義中多RenderFragment 參數, 運行不會有問題, 但如果少定義了 RenderFragment 參數,運行就會報錯
- (5)為了防止使用方多傳子tag, 所有自定義的組件最好都聲明一個 ChildContent RenderFragment 參數
規則(2)的示例說明:
@page "/simplepage" <Counter IncrementAmount="5"> <h1>something</h1> </Counter> <Counter IncrementAmount="5">something</Counter>
@page "/counter" <h1>Counter</h1> <p>Current count: @currentCount</p> <button class="btn btn-primary" @onclick="IncrementCount">Click me</button> @ChildContent @code { [Parameter] public int IncrementAmount{ get; set; } = 1; [Parameter] public RenderFragment ChildContent { get; set; } //必需名為ChildContent private int currentCount = 0; private void IncrementCount() { currentCount= currentCount+ IncrementAmount; } }
規則(3)的示例說明:
@page "/simplepage" <Counter IncrementAmount="5"> <ChildContent2>something</ChildContent2> </Counter>
@page "/counter" <h1>Counter</h1> <p>Current count: @currentCount</p> <button class="btn btn-primary" @onclick="IncrementCount">Click me</button> <br /> ChildContent: @ChildContent <br /> ChildContent2: @ChildContent2 @code { [Parameter] public int IncrementAmount { get; set; } = 1; [Parameter] public RenderFragment ChildContent { get; set; } //增加ChildContent參數, 保險起見 [Parameter] public RenderFragment ChildContent2 { get; set; } //優先被賦值 private int currentCount = 0; private void IncrementCount() { currentCount = currentCount + IncrementAmount; } }
運行效果:

===========================================
帶多個 RenderFragment 參數組件的示例
===========================================
RenderFragment 參數非常適合模版型組件開發, 比如我們要設計一個 Modal Dialog 組件, 該組件大塊顯示內容都由外界傳入, 比如Header/Content/Footer, 另外為了增加通用性, 樣式控制最好開放使用方.
@page "/simplepage" <MyModal> <Header>this is title</Header> <Content>This is content</Content> <Footer> <button type="button" class="btn btn-primary"> Close Dialog </button> </Footer> </MyModal>
@Header <br /> @Content <br /> @Footer @code { [Parameter] public RenderFragment Header { get; set; } [Parameter] public RenderFragment Content { get; set; } [Parameter] public RenderFragment Footer { get; set; } [Parameter] public RenderFragment ChildContent { get; set; } }
效果:


浙公網安備 33010602011771號