Содержание
Шаблонные компоненты — это компоненты, которые получают один или несколько шаблонов пользовательского интерфейса в качестве параметров, которые могут использоваться в логике рендеринга компонента.
При разработке пользовательского интерфейса мы часто сталкиваемся с шаблонными компонентами. Например, компонент таблицы можно условно разделить на три части: заголовок таблицы, содержимое (строки) и нижний колонтитул. Мы можем создать свой шаблонный компонент таблицы и использовать его многократно в различных частях нашего приложения вместо того, чтобы каждый раз в разметке очередной страницы определять стандартный html-элемент <table>. Рассмотрим процесс разработки шаблонного компонента Razor.
Разработка шаблонного компонента
Рассмотрим разработку шаблонного компонента на примере таблицы. Итак, на рисунке ниже показано из каких частей будет состоять наш компонент:
Создадим новый проект Blazor Hybrid, добавим в него новый компонент CoolTable и напишем для этого компонента следующий код:
@typeparam TItem
<table class="table">
<thead>
<tr>@TableHeader</tr>
</thead>
<tbody>
<Virtualize Context="item" TItem="TItem" Items="Items">
<tr>@RowTemplate(item)</tr>
</Virtualize>
</tbody>
<tfoot>
<tr>
@TableFooter
</tr>
</tfoot>
</table>
@code {
[Parameter]
public RenderFragment? TableHeader { get; set; }
[Parameter]
public RenderFragment? TableFooter { get; set; }
[Parameter, EditorRequired]
public RenderFragment<TItem> RowTemplate { get; set; } = default!;
[Parameter, EditorRequired]
public IList<TItem> Items { get; set; } = default!;
}
Рассмотрим этот компонент, начиная с кода C#. Для компонента определено четыре параметра. Первые три — это параметры типа RenderFragment, причем RowTemplate (шаблон строки) — типизированный RenderFragment<TItem>. Как мы уже знаем, тип RenderFragment используется для передачи содержимого из родительского в дочерний компонент. То есть первые три наших компонента — это, по сути, шаблоны для нашей таблицы — заголовок (TableHeader), нижний колонтитул (TableFooter) и содержимое (RowTemplate). Четвертый параметр Items — список элементов, которые должны быть выведены в нашей таблице.
Что касается разметки компонента, то здесь, в первую очередь, необходимо обратить внимание на директиву Razor — @typepatam. Эта директива объявляет параметр универсального типа для класса компонента. То есть запись:
@typeparam TItem
в разметке компонента Razor аналогична записи в код C#
public class MyComponent<Titem>
{
}
Далее, в разметке компонента мы выводим таблицу, используя заданные шаблоны:
<table class="table">
<thead>
<tr>@TableHeader</tr>
</thead>
<tbody>
<Virtualize Context="item" TItem="TItem" Items="Items">
<tr>@RowTemplate(item)</tr>
</Virtualize>
</tbody>
<tfoot>
<tr>
@TableFooter
</tr>
</tfoot>
</table>
При этом, при выводе содержимого таблицы мы применяем уже знакомую нам виртуализацию:
<Virtualize Context="item" TItem="TItem" Items="Items">
<tr>@RowTemplate(item)</tr>
</Virtualize>
Теперь проверим работу нашего компонента. Для этого перейдем в Home.razor и изменим код компонента следующим образом:
@page "/"
<h1>Table</h1>
<CoolTable Items="People" Context="person">
<TableHeader>
<th>ID</th>
<th>Name</th>
<th>Email</th>
</TableHeader>
<RowTemplate>
<td>@person.Id</td>
<td>@person.Name</td>
<td>@person.Email</td>
</RowTemplate>
<TableFooter>
<td>Total</td>
<td>@People.Count</td>
<td></td>
</TableFooter>
</CoolTable>
@code {
private List<Person> People = new()
{
new Person(){ Id=1, Name="Vlad", Email="vlad@mail.ru"},
new Person(){ Id=2, Name="John", Email="john@mail.ru"},
new Person(){ Id=3, Name="Alex", Email="alex@mail.ru"},
};
private class Person
{
public int Id { get; set; }
public string Name { get; set; }
public string Email { get; set; }
}
}
Здесь мы добавили новый класс Person и создали список People, состоящий из трех элементов, который мы и выводим далее в компоненте таблицы. Что касается разметки компонента, то здесь мы, используя определенные в нашем компоненте параметры (типа RenderFragment) определяем содержимое каждой из частей таблицы. При этом, так как в атрибутах компонента CoolTable мы передали список элементов и задали имя контекста
<CoolTable Items="People" Context="person">
@context — это внутренняя переменная, предоставляемая Blazor, которая содержит значение, переданное делегату RenderFragment<T>. Такой делегат у нас в компоненте один — это шаблон содержимого (RowTemplate). Мы могли бы не определять в атрибутах нашего компонента Context и сделать вот такую разметку компонента, обращаясь напрямую к внутренней переменной context:
<RowTemplate>
<td>@context.Id</td>
<td>@context.Name</td>
<td>@context.Email</td>
</RowTemplate>
Результат работы приложения от этого никак не поменяется.
Итого
Шаблонные компоненты — это компоненты, которые получают один или несколько шаблонов пользовательского интерфейса в качестве параметров, которые могут использоваться в логике рендеринга компонента. Шаблонные части компонента обычно определяются в виде параметров с типами RenderFragment или RenderFragment<T>.
