Поделиться через


Создание повторно используемых компонентов пользовательского интерфейса с помощью Blazor

Совет

Это фрагмент из электронной книги для разработчиков ASP NET веб-формы для Azure, Blazor доступных в документации .NET или в виде бесплатного скачиваемого PDF-файла, который можно читать в автономном режиме.

Blazor-for-ASP-NET-Web-Forms-Developers eBook cover эскиз.

Одним из преимуществ ASP.NET Web Forms является инкапсуляция многоразовых фрагментов кода пользовательского интерфейса в повторно используемые элементы управления пользовательского интерфейса. Настраиваемые пользовательские элементы управления могут быть определены в разметке с помощью ASCX-файлов. Кроме того, можно создавать сложные серверные элементы управления в коде с полной поддержкой конструктора.

Blazor также поддерживает инкапсуляцию пользовательского интерфейса через компоненты. Особенности компонента:

  • Это автономный фрагмент пользовательского интерфейса.
  • Поддерживает собственную логику состояния и отрисовки.
  • Может определять обработчики событий пользовательского интерфейса, выполнять привязку к входным данным и управлять собственным жизненным циклом.
  • Обычно определяется в RAZOR-файле с помощью синтаксиса Razor.

Введение в Razor

Razor — это облегченный язык создания шаблонов разметки на основе HTML и C#. С помощью Razor можно легко переходить между разметкой и кодом C#, чтобы определить логику отрисовки компонента. При компиляции RAZOR-файла логика отрисовки записывается структурированным образом в классе .NET. Имя скомпилированного класса берется из имени RAZOR-файла. Пространство имен берется из пространства имен по умолчанию для проекта и пути к папке, либо можно явно указать пространство имен с помощью директивы @namespace (подробнее о директивах Razor ниже).

Логика отрисовки компонента создается с помощью обычной разметки HTML с динамической логикой, добавленной с помощью C#. Символ @ используется для перехода на C#. Razor обычно понимает, когда вы переключаетесь на HTML. Например, следующий компонент отрисовывает тег <p> с текущим временем:

<p>@DateTime.Now</p>

Чтобы явно указать начало и конец выражения C#, используйте круглые скобки:

<p>@(DateTime.Now)</p>

Razor также упрощает использование потока управления C# в логике отрисовки. Например, можно выполнить условную отрисовку HTML-кода следующим образом:

@if (value % 2 == 0)
{
    <p>The value was even.</p>
}

Также можно создать список элементов с помощью обычного цикла C# foreach следующим образом:

<ul>
@foreach (var item in items)
{
    <li>@item.Text</li>
}
</ul>

Директивы Razor, такие как директивы в ASP.NET Web Forms, управляют многими аспектами компиляции компонента Razor. Вот несколько примеров:

  • Пространство имен
  • Базовый класс
  • Реализованные интерфейсы
  • Универсальные параметры
  • Импортированные пространства имен
  • Маршруты

Директивы Razor начинаются с символа @ и обычно используются в начале новой строки в начале файла. Например, директива @namespace определяет пространство имен компонента:

@namespace MyComponentNamespace

В следующей таблице перечислены различные директивы Razor, используемые в Blazor, и их эквиваленты ASP.NET Web Forms, если они существуют.

Директива Описание Пример Эквивалент в Web Forms
@attribute Добавляет атрибут уровня класса в компонент @attribute [Authorize] нет
@code Добавляет члены класса в компонент @code { ... } <script runat="server">...</script>
@implements Реализует заданный интерфейс @implements IDisposable Использование кода программной части
@inherits Наследует от указанного базового класса @inherits MyComponentBase <%@ Control Inherits="MyUserControlBase" %>
@inject Внедряет службу в компонент @inject IJSRuntime JS нет
@layout Задает компонент макета для компонента @layout MainLayout <%@ Page MasterPageFile="~/Site.Master" %>
@namespace Задает пространство имен для компонента @namespace MyNamespace нет
@page Указывает маршрут для компонента @page "/product/{id}" <%@ Page %>
@typeparam Указывает параметр универсального типа для компонента @typeparam TItem Использование кода программной части
@using Указывает пространство имен для переноса в область @using MyComponentNamespace Добавляет пространство имен в web.config

Компоненты Razor также активно используют атрибуты директивы в элементах для управления различными аспектами компиляции компонентов (обработка событий, привязка данных, ссылки на компоненты и элементы и т. д.). Все атрибуты директивы следуют общему универсальному синтаксису, в котором значения в круглых скобках являются необязательными:

@directive(-suffix(:name))(="value")

В следующей таблице перечислены различные атрибуты директив Razor, используемые в Blazor.

Атрибут Описание Пример
@attributes Преобразует для просмотра словарь атрибутов <input @attributes="ExtraAttributes" />
@bind Создает двустороннюю привязку данных <input @bind="username" @bind:event="oninput" />
@on{event} Добавляет обработчик событий для указанного события <button @onclick="IncrementCount">Click me!</button>
@key Задает ключ, используемый алгоритмом сравнения для сохранения элементов в коллекции <DetailsEditor @key="person" Details="person.Details" />
@ref Получает ссылку на компонент или HTML-элемент <MyDialog @ref="myDialog" />

Различные атрибуты директивы, используемые Blazor (@onclick, @bind, @ref и т. д.), описаны в разделах ниже и последующих главах.

Многие из синтаксисов, используемые в ASPX и ASCX-файлах имеют параллельные синтаксисы в Razor. Ниже приведено простое сравнение синтаксиса для ASP.NET Web Forms и Razor.

Функция Веб-формы Синтаксис Бритва Синтаксис
Директивы <%@ [directive] %> <%@ Page %> @[directive] @page
Блоки кода <% %> <% int x = 123; %> @{ } @{ int x = 123; }
Выражения
(В кодировке HTML)
<%: %> <%:DateTime.Now %> Неявно: @
Явно: @()
@DateTime.Now
@(DateTime.Now)
Комментарии <%-- --%> <%-- Commented --%> @* *@ @* Commented *@
Привязка данных <%# %> <%# Bind("Name") %> @bind <input @bind="username" />

Чтобы добавить члены в класс компонента Razor, используйте директиву @code. Этот метод аналогичен использованию блока <script runat="server">...</script> в пользовательском элементе управления или на странице ASP.NET Web Forms.

@code {
    int count = 0;

    void IncrementCount()
    {
        count++;
    }
}

Поскольку Razor основан на C#, он должен быть скомпилирован из проекта C# (.csproj). RAZOR-файлы нельзя компилировать из проекта Visual Basic (.vbproj). Однако вы можете ссылаться на проекты Visual Basic из проекта Blazor. Верно и обратное.

Полный справочник по синтаксису Razor см. в статье Справочник по синтаксису Razor для ASP.NET Core.

Использование компонентов

Помимо обычного HTML, компоненты также могут использовать другие компоненты как часть логики отрисовки. Синтаксис использования компонента в Razor подобен использованию пользовательского элемента управления в приложении ASP.NET Web Forms. Компоненты указываются с помощью тега элемента, соответствующего имени типа компонента. Например, вы можете добавить компонент Counter:

<Counter />

В отличие от ASP.NET Web Forms, компоненты в Blazor:

  • Не используют префикс элемента (например, asp:).
  • Не требуют регистрации на странице или в web.config.

Компоненты Razor можно сравнить с типами .NET, так как, по сути, именно это они собой и представляют. Если имеется ссылка на сборку, содержащую компонент, то компонент доступен для использования. Чтобы перенести пространство имен компонента в область, примените директиву @using:

@using MyComponentLib

<Counter />

Как видно в проектах по умолчанию Blazor, директивы @using можно размещать в файле _Imports.razor, чтобы импортировать их во все RAZOR-файлы в одном и том же каталоге и в дочерних каталогах.

Если пространство имен для компонента не находится в области, можно указать компонент, используя его полное имя типа, как в C#:

<MyComponentLib.Counter />

Изменение заголовка страницы на основе компонентов

При создании приложений в стиле SPA часто перезагружаются части страницы без перезагрузки всей страницы. Даже в таком случае, возможно, будет полезно, если заголовок страницы будет изменяться в зависимости от того, какой компонент сейчас загружен. Чтобы реализовать такое поведение, включите тег <PageTitle> в страницу Razor компонента:

@page "/"
<PageTitle>Home</PageTitle>

Содержимое этого элемента может быть динамическим, например, может отображаться текущее число сообщений:

<PageTitle>@MessageCount messages</PageTitle>

Обратите внимание, что, если несколько компонентов на определенной странице содержат теги <PageTitle>, будет отображаться только последний из них (так как каждый новый тег перезаписывает предыдущий).

Параметры компонентов

В ASP.NET Web Forms можно передавать параметры и данные в элементы управления с помощью общедоступных свойств. Эти свойства можно задать в разметке с помощью атрибутов или непосредственно в коде. Компоненты Razor работают аналогично, хотя свойства компонента также должны быть помечены атрибутом [Parameter] , чтобы считаться параметрами компонента.

Следующий компонент Counter определяет параметр компонента с именем IncrementAmount, который можно использовать для указания величины приращения Counter при каждом нажатии кнопки.

<h1>Counter</h1>

<p>Current count: @currentCount</p>

<button class="btn btn-primary" @onclick="IncrementCount">Click me</button>

@code {
    int currentCount = 0;

    [Parameter]
    public int IncrementAmount { get; set; } = 1;

    void IncrementCount()
    {
        currentCount+=IncrementAmount;
    }
}

Чтобы указать параметр компонента в Blazor, используйте атрибут, как в ASP.NET Web Forms:

<Counter IncrementAmount="10" />

Параметры строки запроса

Компоненты Razor также могут использовать значения из строки запроса страницы, на которой они отображаются в качестве источника параметров. Чтобы реализовать это поведение, добавьте в параметр атрибут [SupplyParameterFromQuery]. Например, следующее определение параметра получит значение из запроса в виде ?IncBy=2:

[Parameter]
[SupplyParameterFromQuery(Name = "IncBy")]
public int IncrementAmount { get; set; } = 1;

Если вы не укажете пользовательское значение Name в атрибуте [SupplyParameterFromQuery], по умолчанию будет указано имя свойства (в нашем случае это IncrementAmount).

Компоненты и границы ошибок

По умолчанию приложения Blazor будут обнаруживать необработанные исключения. В таком случае в нижней части страницы отображается сообщение об ошибке без дополнительных сведений. Чтобы ограничить части приложения, затрагиваемые необработанной ошибкой, например, чтобы ограничить воздействие на один компонент, объявления компонента можно поместить в оболочку тега <ErrorBoundary>.

Например, для защиты от возможных исключений, вызванных компонентом Counter, объявите его в <ErrorBoundary> и при необходимости приведите сообщение, которое будет отображаться при возникновении исключения:

<ErrorBoundary>
    <ChildContent>
        <Counter />
    </ChildContent>
    <ErrorContent>
        Oops! The counter isn't working right now; please try again later.
    </ErrorContent>
</ErrorBoundary>

Если вам не нужно включать пользовательское содержимое в сообщение об ошибке, можно просто поместить компонент в оболочку напрямую:

<ErrorBoundary>
  <Counter />
</ErrorBoundary>

Сообщение по умолчанию о том, что произошло сообщение об ошибке. Если необработанное исключение возникает в упакованном компоненте.

Обработчики событий

ASP.NET Web Forms и Blazor предоставляют модель программирования на основе событий для обработки событий пользовательского интерфейса. Примеры таких событий включают нажатие кнопок и ввод текста. В ASP.NET Web Forms используются серверные элементы управления HTML для работы с событиями пользовательского интерфейса, предоставляемыми моделью DOM. Или вы можете обрабатывать события, предоставляемые элементами управления веб-сервера. События поступают на сервер посредством запросов обратной передачи. Рассмотрим следующие примеры кнопок Web Forms:

Counter.ascx

<asp:Button ID="ClickMeButton" runat="server" Text="Click me!" OnClick="ClickMeButton_Click" />

Counter.ascx.cs

public partial class Counter : System.Web.UI.UserControl
{
    protected void ClickMeButton_Click(object sender, EventArgs e)
    {
        Console.WriteLine("The button was clicked!");
    }
}

В Blazor можно зарегистрировать обработчики для событий пользовательского интерфейса DOM напрямую с помощью атрибутов директивы в форме @on{event}. Заполнитель {event} представляет имя события. Например, можно ожидать нажатие кнопок следующим образом:

<button @onclick="OnClick">Click me!</button>

@code {
    void OnClick()
    {
        Console.WriteLine("The button was clicked!");
    }
}

Обработчики событий могут принимать необязательный аргумент, относящийся к конкретному событию, для предоставления дополнительных сведений о событии. Например, события мыши могут принимать аргумент MouseEventArgs, но это не обязательно.

<button @onclick="OnClick">Click me!</button>

@code {
    void OnClick(MouseEventArgs e)
    {
        Console.WriteLine($"Mouse clicked at {e.ScreenX}, {e.ScreenY}.");
    }
}

Вместо ссылки на группу методов для обработчика событий можно использовать лямбда-выражение. Лямбда-выражение позволяет закрывать другие значения в области.

@foreach (var buttonLabel in buttonLabels)
{
    <button @onclick="() => Console.WriteLine($"The {buttonLabel} button was clicked!")">@buttonLabel</button>
}

Обработчики событий могут выполняться синхронно или асинхронно. Например, следующий обработчик событий OnClick выполняется асинхронно:

<button @onclick="OnClick">Click me!</button>

@code {
    async Task OnClick()
    {
        var result = await Http.GetAsync("api/values");
    }
}

После обработки события компонент преобразуется для просмотра с учетом изменений состояния компонента. При использовании асинхронных обработчиков событий компонент преобразуется для просмотра сразу после выполнения обработчика. Компонент отрисовывается снова после выполнения асинхронной задачи Task. Этот асинхронный режим выполнения позволяет визуализировать соответствующий пользовательский интерфейс во время выполнения асинхронной задачи Task.

<button @onclick="ShowMessage">Get message</button>

@if (showMessage)
{
    @if (message == null)
    {
        <p><em>Loading...</em></p>
    }
    else
    {
        <p>The message is: @message</p>
    }
}

@code
{
    bool showMessage = false;
    string message;

    public async Task ShowMessage()
    {
        showMessage = true;
        message = await MessageService.GetMessageAsync();
    }
}

Компоненты также могут определять собственные события, определяя параметр компонента типа EventCallback<TValue>. Обратные вызовы событий поддерживают все разновидности обработчиков событий пользовательского интерфейса DOM: необязательные аргументы, синхронные или асинхронные операции, группы методов или лямбда-выражения.

<button class="btn btn-primary" @onclick="OnClick">Click me!</button>

@code {
    [Parameter]
    public EventCallback<MouseEventArgs> OnClick { get; set; }
}

Привязка данных

Blazor предоставляет простой механизм привязки данных из компонента пользовательского интерфейса к состоянию компонента. Этот подход отличается от функций в ASP.NET Web Forms для привязки данных из источников данных к элементам управления пользовательского интерфейса. Мы обсудим обработку данных из различных источников данных в разделе Работа с данными.

Чтобы создать двустороннюю привязку данных из компонента пользовательского интерфейса к состоянию компонента, используйте атрибут директивы @bind. В следующем примере значение флажка привязано к полю isChecked.

<input type="checkbox" @bind="isChecked" />

@code {
    bool isChecked;
}

При подготовке компонента к просмотру значение флажка устанавливается равным значению поля isChecked. Когда пользователь переключает флажок, событие onchange срабатывает и для поля isChecked задается новое значение. Синтаксис @bind в этом случае эквивалентен следующей разметке:

<input value="@isChecked" @onchange="(UIChangeEventArgs e) => isChecked = e.Value" />

Чтобы изменить событие, используемое для привязки, используйте атрибут @bind:event.

<input @bind="text" @bind:event="oninput" />
<p>@text</p>

@code {
    string text;
}

Компоненты также могут поддерживать привязку данных к параметрам. Для привязки данных определите параметр обратного вызова события с тем же именем, что и у привязываемого параметра. К имени добавляется суффикс "Changed".

PasswordBox.razor

Password: <input
    value="@Password"
    @oninput="OnPasswordChanged"
    type="@(showPassword ? "text" : "password")" />

<label><input type="checkbox" @bind="showPassword" />Show password</label>

@code {
    private bool showPassword;

    [Parameter]
    public string Password { get; set; }

    [Parameter]
    public EventCallback<string> PasswordChanged { get; set; }

    private Task OnPasswordChanged(ChangeEventArgs e)
    {
        Password = e.Value.ToString();
        return PasswordChanged.InvokeAsync(Password);
    }
}

Чтобы связать привязку данных с базовым элементом пользовательского интерфейса, установите значение и обработайте событие непосредственно в элементе пользовательского интерфейса, а не с помощью атрибута @bind.

Для привязки к параметру компонента используйте атрибут @bind-{Parameter}, чтобы указать параметр, с которым необходимо выполнить привязку.

<PasswordBox @bind-Password="password" />

@code {
    string password;
}

Изменения состояний

Если состояние компонента изменилось за пределами обычного пользовательского интерфейса или обратного вызова события, компонент должен вручную сообщить о необходимости повторной отрисовки. Чтобы сообщить о том, что состояние компонента изменилось, вызовите метод StateHasChanged для компонента.

В приведенном ниже примере компонент отображает сообщение из службы AppState, которая может быть обновлена другими частями приложения. Компонент регистрирует свой метод StateHasChanged с событием AppState.OnChange, чтобы компонент преобразовывался для просмотра при каждом обновлении сообщения.

public class AppState
{
    public string Message { get; }

    // Lets components receive change notifications
    public event Action OnChange;

    public void UpdateMessage(string message)
    {
        Message = message;
        NotifyStateChanged();
    }

    private void NotifyStateChanged() => OnChange?.Invoke();
}
@inject AppState AppState

<p>App message: @AppState.Message</p>

@code {
    protected override void OnInitialized()
    {
        AppState.OnChange += StateHasChanged
    }
}

Жизненный цикл компонента

Платформа ASP.NET Web Forms имеет четко определенные методы жизненного цикла для модулей, страниц и элементов управления. Например, следующий элемент управления реализует обработчики событий для событий жизненного цикла Init, Load и UnLoad:

Counter.ascx.cs

public partial class Counter : System.Web.UI.UserControl
{
    protected void Page_Init(object sender, EventArgs e) { ... }
    protected void Page_Load(object sender, EventArgs e) { ... }
    protected void Page_UnLoad(object sender, EventArgs e) { ... }
}

Компоненты Razor также имеют четко определенный жизненный цикл. Жизненный цикл компонента можно использовать для инициализации состояния компонента и реализации дополнительного поведения компонентов.

Все методы жизненного цикла компонента Blazor имеют как синхронные, так и асинхронные версии. Преобразование компонента для просмотра является синхронным. Асинхронную логику нельзя выполнять в процессе преобразования компонента для просмотра. Вся асинхронная логика должна выполняться как часть метода жизненного цикла async.

OnInitialized

Методы OnInitialized и OnInitializedAsync используются для инициализации компонента. Обычно компонент инициализируется после первой отрисовки. После инициализации компонента он может быть отрисован несколько раз, прежде чем будет удален в конечном итоге. Метод OnInitialized аналогичен событию Page_Load на страницах и в элементах управления ASP.NET Web Forms.

protected override void OnInitialized() { ... }
protected override async Task OnInitializedAsync() { await ... }

OnParametersSet

Методы OnParametersSet и OnParametersSetAsync вызываются, когда компонент получил параметры от своего родительского элемента, и значение присваивается свойствам. Эти методы выполняются после инициализации компонента и при каждой отрисовке компонента.

protected override void OnParametersSet() { ... }
protected override async Task OnParametersSetAsync() { await ... }

OnAfterRender

Методы OnAfterRender и OnAfterRenderAsync вызываются после завершения отрисовки компонента. Ссылки на элементы и компоненты заполняются на этом этапе (подробнее об этих концепциях см. ниже). На этом этапе включается интерактивное взаимодействие с браузером. Может происходить взаимодействие с моделью DOM и выполнение JavaScript.

protected override void OnAfterRender(bool firstRender)
{
    if (firstRender)
    {
        ...
    }
}
protected override async Task OnAfterRenderAsync(bool firstRender)
{
    if (firstRender)
    {
        await ...
    }
}

OnAfterRender и OnAfterRenderAsyncне вызываются при предварительной отрисовке на сервере.

Параметр firstRender имеет значение true при первой отрисовке компонента. В остальных случаях он имеет значение false.

IDisposable

Компоненты Razor могут реализовываться IDisposable для удаления ресурсов при удалении компонента из пользовательского интерфейса. Компонент Razor может реализовать IDispose с помощью директивы @implements:

@using System
@implements IDisposable

...

@code {
    public void Dispose()
    {
        ...
    }
}

Сбор ссылок на компонент

В ASP.NET Web Forms можно управлять экземпляром элемента управления непосредственно в коде, ссылаясь на его идентификатор. В Blazor также можно получить ссылку на компонент и использовать ее, хотя это происходит реже.

Чтобы записать ссылку на компонент в Blazor, используйте атрибут директивы @ref. Значение атрибута должно совпадать с именем настраиваемого поля, имеющего тот же тип, что и компонент, на который указывает ссылка.

<MyLoginDialog @ref="loginDialog" ... />

@code {
    MyLoginDialog loginDialog = default!;

    void OnSomething()
    {
        loginDialog.Show();
    }
}

При отрисовке родительского компонента поле заполняется экземпляром дочернего компонента. Затем можно вызывать методы в экземпляре компонента или иным образом использовать его.

Не рекомендуется напрямую обрабатывать состояние компонента с помощью ссылок на компоненты. Это помешает автоматической отрисовке компонента в нужное время.

Запись ссылок на элементы

Компоненты Razor могут записывать ссылки на элемент. В отличие от серверных элементов управления HTML в ASP.NET Web Forms, с моделью DOM нельзя работать напрямую с помощью ссылки на элемент в Blazor. Blazor обрабатывает большинство взаимодействий DOM с помощью алгоритма сравнения DOM. Записанные ссылки на элементы в Blazor являются непрозрачными. Однако они используются для передачи определенной ссылки на элемент в вызове взаимодействия JavaScript. Дополнительные сведения о взаимодействии JavaScript см. в разделе Взаимодействие ASP.NET Core Blazor JavaScript.

Шаблонные компоненты

В ASP.NET Web Forms можно создавать элементы управления — шаблоны. Элементы управления — шаблоны позволяют разработчику указать часть HTML-кода, используемую для отрисовки контейнерного элемента управления. Механизм создания серверных элементов управления — шаблонов является сложным, но он позволяет создавать эффективные сценарии для отрисовки данных настраиваемым пользователем способом. Примеры элементов управления — шаблонов включают Repeater и DataList.

Компоненты Razor также можно шаблонировать, определив параметры компонента типа RenderFragment или RenderFragment<T>. RenderFragment представляет фрагмент разметки Razor, который затем может быть визуализирован компонентом. RenderFragment<T> — это фрагмент разметки Razor, принимающий параметр, который может быть указан при отрисовке фрагмента.

Дочернее содержимое

Компоненты Razor могут записывать дочернее содержимое в виде RenderFragment содержимого и отображать это содержимое как часть отрисовки компонента. Чтобы записать дочернее содержимое, определите параметр компонента типа RenderFragment и присвойте ему имя ChildContent.

ChildContentComponent.razor

<h1>Component with child content</h1>

<div>@ChildContent</div>

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

После этого родительский компонент может предоставить дочернее содержимое, используя обычный синтаксис Razor.

<ChildContentComponent>
    <ChildContent>
        <p>The time is @DateTime.Now</p>
    </ChildContent>
</ChildContentComponent>

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

Шаблонный компонент Razor также может определять несколько параметров компонента типа RenderFragment или RenderFragment<T>. Параметр для RenderFragment<T> можно указать при вызове. Чтобы указать параметр универсального типа для компонента, используйте директиву Razor @typeparam.

SimpleListView.razor

@typeparam TItem

@Heading

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

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

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

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

При использовании шаблонного компонента параметры шаблона можно задать с помощью дочерних элементов, имена которых совпадают с именами параметров. Аргументы компонента типа RenderFragment<T>, переданные как элементы, имеют неявный параметр context. Вы можете изменить имя неявного параметра с помощью атрибута Context в дочернем элементе. Параметр универсального типа можно указать с помощью атрибута, совпадающего с именем параметра типа. Параметр типа будет выведен, если это возможно:

<SimpleListView Items="messages" TItem="string">
    <Heading>
        <h1>My list</h1>
    </Heading>
    <ItemTemplate Context="message">
        <p>The message is: @message</p>
    </ItemTemplate>
</SimpleListView>

Выходные данные этого компонента имеют следующий вид:

<h1>My list</h1>
<ul>
    <li><p>The message is: message1</p></li>
    <li><p>The message is: message2</p></li>
<ul>

Поддерживающий код

Компонент Razor обычно создается в одном razor-файле . Однако можно разделить код и разметку с помощью файла кода программной части. Чтобы использовать файл компонента, добавьте файл C#, соответствующий имени файла компонента, но с расширением .cs (Counter.razor.cs). Используйте файл C#, чтобы определить базовый класс для компонента. Вы можете присвоить любое имя базовому классу, хотя обычно имя класса совпадает с классом компонента, но имеет расширение Base (CounterBase). Класс на основе компонента также должен быть производным от ComponentBase. Затем в файле компонента Razor добавьте директиву @inherits, чтобы указать базовый класс для компонента (@inherits CounterBase).

Counter.razor

@inherits CounterBase

<h1>Counter</h1>

<p>Current count: @currentCount</p>

<button @onclick="IncrementCount">Click me</button>

Counter.razor.cs

public class CounterBase : ComponentBase
{
    protected int currentCount = 0;

    protected void IncrementCount()
    {
        currentCount++;
    }
}

Видимость членов компонента в базовом классе должна быть protected или public, чтобы у класса компонента был доступ.

Дополнительные ресурсы

Предыдущее не является исчерпывающим лечением всех аспектов компонентов Razor. Дополнительные сведения о создании и использовании компонентов Razor ASP.NET Core см в документации по Blazor.