Шаблонные компоненты Blazor в ASP.NET CoreASP.NET Core Blazor templated components

Авторы: Люк Латэм (Luke Latham) и Дэниэл Рот (Daniel Roth)By Luke Latham and Daniel Roth

Шаблонные компоненты — это компоненты, которые могут принимать один или несколько шаблонов пользовательского интерфейса в качестве параметров, используемых затем как часть логики отрисовки компонента.Templated components are components that accept one or more UI templates as parameters, which can then be used as part of the component's rendering logic. Шаблонные компоненты позволяют разрабатывать более общие компоненты, которые удобнее использовать повторно, чем обычные.Templated components allow you to author higher-level components that are more reusable than regular components. Вот несколько примеров:A couple of examples include:

  • компонент таблицы, позволяющий пользователю задавать шаблоны для заголовка, строк и нижнего колонтитула таблицы;A table component that allows a user to specify templates for the table's header, rows, and footer.
  • компонент списка, позволяющий пользователю задавать шаблон для отрисовываемых элементов списка.A list component that allows a user to specify a template for rendering items in a list.

Просмотреть или скачать образец кода (как скачивать)View or download sample code (how to download)

Параметры шаблонаTemplate parameters

Шаблонный компонент определяется путем указания одного или нескольких параметров компонента типа RenderFragment или RenderFragment<TValue>.A templated component is defined by specifying one or more component parameters of type RenderFragment or RenderFragment<TValue>. Фрагмент отрисовки представляет часть пользовательского интерфейса, подлежащую отрисовке.A render fragment represents a segment of UI to render. RenderFragment<TValue> принимает параметр типа, который можно задать при вызове фрагмента отрисовки.RenderFragment<TValue> takes a type parameter that can be specified when the render fragment is invoked.

Компонент TableTemplate (TableTemplate.razor):TableTemplate component (TableTemplate.razor):

@typeparam TItem

<table class="table">
    <thead>
        <tr>@TableHeader</tr>
    </thead>
    <tbody>
        @foreach (var item in Items)
        {
            <tr>@RowTemplate(item)</tr>
        }
    </tbody>
</table>

@code {
    [Parameter]
    public RenderFragment TableHeader { get; set; }

    [Parameter]
    public RenderFragment<TItem> RowTemplate { get; set; }

    [Parameter]
    public IReadOnlyList<TItem> Items { get; set; }
}

При использовании шаблонного компонента параметры шаблона можно задать с помощью дочерних элементов, имена которых совпадают с именами параметров (TableHeader и RowTemplate в следующем примере):When using a templated component, the template parameters can be specified using child elements that match the names of the parameters (TableHeader and RowTemplate in the following example):

<TableTemplate Items="pets">
    <TableHeader>
        <th>ID</th>
        <th>Name</th>
    </TableHeader>
    <RowTemplate>
        <td>@context.PetId</td>
        <td>@context.Name</td>
    </RowTemplate>
</TableTemplate>

@code {
    private List<Pet> pets = new List<Pet>
    {
        new Pet { PetId = 2, Name = "Mr. Bigglesworth" },
        new Pet { PetId = 4, Name = "Salem Saberhagen" },
        new Pet { PetId = 7, Name = "K-9" }
    };

    private class Pet
    {
        public int PetId { get; set; }
        public string Name { get; set; }
    }
}

Примечание

Ограничения универсального типа будут поддерживаться в будущих выпусках.Generic type constraints will be supported in a future release. Дополнительные сведения см. в разделе Разрешение ограничений универсального типа (dotnet/aspnetcore #8433).For more information, see Allow generic type constraints (dotnet/aspnetcore #8433).

Параметры контекста шаблонаTemplate context parameters

Аргументы компонента типа RenderFragment<TValue>, передаваемые как элементы, имеют неявный параметр context (например, @context.PetId в предыдущем примере кода), но его имя можно изменить с помощью атрибута Context дочернего элемента.Component arguments of type RenderFragment<TValue> passed as elements have an implicit parameter named context (for example from the preceding code sample, @context.PetId), but you can change the parameter name using the Context attribute on the child element. В следующем примере атрибут Context элемента RowTemplate задает имя параметра pet:In the following example, the RowTemplate element's Context attribute specifies the pet parameter:

<TableTemplate Items="pets">
    <TableHeader>
        <th>ID</th>
        <th>Name</th>
    </TableHeader>
    <RowTemplate Context="pet">
        <td>@pet.PetId</td>
        <td>@pet.Name</td>
    </RowTemplate>
</TableTemplate>

@code {
    ...
}

Кроме того, атрибут Context можно задать для элемента компонента.Alternatively, you can specify the Context attribute on the component element. Заданный атрибут Context применяется ко всем указанным параметрам шаблона.The specified Context attribute applies to all specified template parameters. Это может быть полезно, если необходимо указать имя параметра содержимого для неявного дочернего содержимого (без содержащего дочернего элемента).This can be useful when you want to specify the content parameter name for implicit child content (without any wrapping child element). В следующем примере элемент TableTemplate имеет атрибут Context, который применяется ко всем параметрам шаблона:In the following example, the Context attribute appears on the TableTemplate element and applies to all template parameters:

<TableTemplate Items="pets" Context="pet">
    <TableHeader>
        <th>ID</th>
        <th>Name</th>
    </TableHeader>
    <RowTemplate>
        <td>@pet.PetId</td>
        <td>@pet.Name</td>
    </RowTemplate>
</TableTemplate>

@code {
    ...
}

Компоненты универсального типаGeneric-typed components

Шаблонные компоненты часто имеют универсальный тип.Templated components are often generically typed. Например, универсальный компонент ListViewTemplate (ListViewTemplate.razor) можно использовать для отрисовки значений IEnumerable<T>.For example, a generic ListViewTemplate component (ListViewTemplate.razor) can be used to render IEnumerable<T> values. Чтобы определить универсальный компонент, используйте директиву @typeparam и укажите параметры типа:To define a generic component, use the @typeparam directive to specify type parameters:

@typeparam TItem

<ul>
    @foreach (var item in Items)
    {
        @ItemTemplate(item)
    }
</ul>

@code {
    [Parameter]
    public RenderFragment<TItem> ItemTemplate { get; set; }

    [Parameter]
    public IReadOnlyList<TItem> Items { get; set; }
}

При использовании компонентов универсального типа параметр типа выводится, если это возможно:When using generic-typed components, the type parameter is inferred if possible:

<ListViewTemplate Items="pets">
    <ItemTemplate Context="pet">
        <li>@pet.Name</li>
    </ItemTemplate>
</ListViewTemplate>

@code {
    private List<Pet> pets = new List<Pet>
    {
        new Pet { Name = "Mr. Bigglesworth" },
        new Pet { Name = "Salem Saberhagen" },
        new Pet { Name = "K-9" }
    };

    private class Pet
    {
        public string Name { get; set; }
    }
}

В противном случае параметр типа необходимо указать явно с помощью атрибута, совпадающего с именем параметра типа.Otherwise, the type parameter must be explicitly specified using an attribute that matches the name of the type parameter. В следующем примере TItem="Pet" задает тип:In the following example, TItem="Pet" specifies the type:

<ListViewTemplate Items="pets" TItem="Pet">
    <ItemTemplate Context="pet">
        <li>@pet.Name</li>
    </ItemTemplate>
</ListViewTemplate>

@code {
    ...
}