前言
似乎很久没有写 Blazor 的东西了,因为我感觉我写的差不多了。现在觉得可能还需要补充一些细节,比如这个 RenderFragment
和 RenderFragment<TValue>
的使用,
RenderFragment
Represents a segment of UI content, implemented as a delegate that writes the content to a Microsoft.AspNetCore.Components.Rendering.RenderTreeBuilder.
表示UI内容的一个片段,作为一个将内容写入到Microsoft.AspNetCore.Components.Rendering.RenderTreeBuilder
的委托实现。
public delegate void RenderFragment(RenderTreeBuilder builder);
RenderFragment<TValue>
Represents a segment of UI content for an object of type TValue, implemented as a function that returns a Microsoft.AspNetCore.Components.RenderFragment.
表示类型为 TValue
的对象的UI内容段,已实现作为一个函数,返回一个 Microsoft.AspNetCore.Components.RenderFragment
。
public delegate RenderFragment RenderFragment<TValue>(TValue value);
示例
使用 .razor 创建组件
首先定义一个 Table.razor
组件
<table class="table table-striped">
<thead>
<tr>
@Header
</tr>
</thead>
<tbody>
@if (DataSource != null)
{
foreach (var item in DataSource)
{
<tr>
@Body(item)
</tr>
}
}
</tbody>
</table>
@typeparam T
@code {
[Parameter] public IEnumerable<T> DataSource { get; set; }
[Parameter] public RenderFragment Header { get; set; }
[Parameter] public RenderFragment<T> Body { get; set; }
}
使用这个组件:
@if (forecasts == null)
{
<p><em>Loading...</em></p>
}
else
{
<Table DataSource="forecasts">
<Header>
<th>Date</th>
<th>Temp. (C)</th>
<th>Temp. (F)</th>
<th>Summary</th>
</Header>
<Body>
<td>@context.Date.ToShortDateString()</td>
<td>@context.TemperatureC</td>
<td>@context.TemperatureF</td>
<td>@context.Summary</td>
</Body>
</Table>
}
@code {
private WeatherForecast[] forecasts;
protected override async Task OnAfterRenderAsync(bool firstRender)
{
if (firstRender)
{
forecasts = await ForecastService.GetForecastAsync(DateTime.Now);
}
}
}
Header
参数是一个自定义的 UI 代码块,这个应该很好理解。
Body
参数也是一个自定义的 UI 代码块,不同的是它具备一个 context
参数,数据类型是一个泛型类型,也就是 DataSource
定义的 T
的类型,也就是 context
的数据类型就是 T
的类型。
使用 RenderTreeBuilder 创建组件
public class Table<T> : ComponentBase
{
[Parameter] public IEnumerable<T> DataSource { get; set; }
[Parameter] public RenderFragment Header { get; set; }
[Parameter] public RenderFragment<T> Body { get; set; }
protected override void BuildRenderTree(RenderTreeBuilder builder)
{
builder.OpenElement(0, "table"); //table
builder.AddAttribute(1, "class", "table table-striped");
builder.AddContent(2, table =>
{
#region thead
table.OpenElement(0, "thead");
table.AddContent(1, tr =>
{
tr.OpenElement(0, "tr");
tr.AddContent(1, Header);
tr.CloseElement();
});
table.CloseElement();
#endregion
#region tbody
if (DataSource != null)
{
table.OpenElement(10, "tbody");
foreach (var item in DataSource)
{
table.AddContent(11, tr =>
{
tr.OpenElement(0, "tr");
tr.AddContent(1, Body(item));
tr.CloseElement();
});
}
table.CloseElement();
}
#endregion
});
builder.CloseElement(); //table end
}
}
总结
RenderFragment
是一个 UI 片段,用于定义一个参数可以接受任何 HTML 的内容;
RenderFragment<TValue>
是可以在这一块的 UI 片段中附带一个指定数据类型的 context
变量,因此这段代码就可以在合适的地方使用这个变量进行操作。