深入浅出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; } }
效果:
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 单元测试从入门到精通
· 上周热点回顾(3.3-3.9)
· winform 绘制太阳,地球,月球 运作规律
2018-10-08 docker 系列 - 容器数据持久化和数据共享