Предоставление общего доступа к данным в приложениях Blazor
- 7 мин
Blazor включает несколько способов обмена информацией между компонентами. Можно использовать параметры компонента или каскадные параметры для отправки значений из родительского компонента в дочерний компонент. Шаблон AppState — это другой подход, который можно использовать для хранения значений и доступа к ним из любого компонента в приложении.
Предположим, вы работаете на новом веб-сайте доставки пиццы. На домашней странице одинаково должно отображаться несколько пицц. Вы хотите представить пиццы, создавая дочерний компонент для каждой из них. Теперь вы хотите передать идентификатор этому дочернему компоненту, который будет определять, какую пиццу он отображает. Вы также хотите хранить и отображать значение на нескольких компонентах, которое показывает общее количество пицц, которые вы продали сегодня.
В этом уроке вы узнаете три различных метода, которые можно использовать для совместного использования значений между двумя или несколькими компонентами Blazor.
Совместное использование сведений с другими компонентами с помощью параметров компонента
В веб-приложении Blazor каждый компонент отрисовывает часть HTML. Некоторые компоненты отображают полную страницу, но другие отображают небольшие фрагменты разметки, такие как таблица, форма или один элемент управления. Если компонент отображает только раздел разметки, его необходимо использовать в качестве дочернего компонента в родительском компоненте. Компонент вашего ребенка также может быть родителем для других, меньших компонентов, которые в нем отображаются. Дочерние компоненты также называются вложенными компонентами.
В иерархии компонентов, где есть родительские и дочерние элементы, можно обмениваться сведениями с помощью параметров компонента . Определите эти параметры для дочерних компонентов, а затем задайте их значения в родительском элементе. Например, если у вас есть дочерний компонент, отображающий фотографии пиццы, можно использовать параметр компонента для передачи идентификатора пиццы. Дочерний компонент находит пиццу по идентификатору и получает изображения и другие данные. Если вы хотите отобразить множество разных пицц, этот дочерний компонент можно использовать несколько раз на одной родительской странице, передавая другой идентификатор каждому ребенку.
Начните с определения параметра компонента в дочернем компоненте. Вы определяете его как общедоступное свойство C# и украшаете его атрибутом [Parameter] :
<h2>New Pizza: @PizzaName</h2>
<p>@PizzaDescription</p>
@code {
[Parameter]
public string PizzaName { get; set; }
[Parameter]
public string PizzaDescription { get; set; } = "The best pizza you've ever tasted."
}
Так как параметры компонента являются членами дочернего компонента, их можно отобразить в HTML с помощью зарезервированного @ символа Blazor, а затем их имени. Кроме того, приведенный выше код задает значение по умолчанию для параметра PizzaDescription. Это значение отображается, если родительский компонент не передает значение. В противном случае значение, переданное из родительского элемента, заменяет его.
Вы также можете использовать пользовательские классы в проекте в качестве параметров компонента. Рассмотрим этот класс, описывающий начинку:
public class PizzaTopping
{
public string Name { get; set; }
public string Ingredients { get; set; }
}
Этот параметр можно использовать в качестве параметра компонента так же, как и значение параметра для доступа к отдельным свойствам класса с помощью синтаксиса dot:
<h2>New Topping: @Topping.Name</h2>
<p>Ingredients: @Topping.Ingredients</p>
@code {
[Parameter]
public PizzaTopping Topping { get; set; }
}
В родительском компоненте необходимо задать значения параметров с помощью атрибутов тегов дочернего компонента. Вы устанавливаете простые компоненты напрямую. При использовании параметра на основе пользовательского класса вы используете встроенный код C# для создания нового экземпляра этого класса и задания его значений:
@page "/pizzas-toppings"
<h1>Our Latest Pizzas and Topping</h1>
<Pizza PizzaName="Hawaiian" PizzaDescription="The one with pineapple" />
<PizzaTopping Topping="@(new PizzaTopping() { Name = "Chilli Sauce", Ingredients = "Three kinds of chilli." })" />
Предоставление общего доступа к данным с помощью каскадных параметров
Параметры компонента хорошо работают, если требуется передать значение непосредственному дочернему элементу компонента. Вещи становятся неловкими, когда у вас есть глубокая иерархия с детьми детей и т. д. Параметры компонента не передаются в компоненты потомков из компонентов предков или ниже по иерархии. Чтобы справиться с этой проблемой элегантно, Blazor включает каскадные параметры. Если задать значение каскадного параметра в компоненте, его значение автоматически доступно для всех потомков на любую глубину.
В родительском компоненте с помощью тега <CascadingValue> указывается информация, которая будет каскадировать ко всем потомкам. Этот тег реализуется как встроенный компонент Blazor. Любой компонент, отрисованный в этом теге, может получить доступ к значению.
@page "/specialoffers"
<h1>Special Offers</h1>
<CascadingValue Name="DealName" Value="Throwback Thursday">
<!-- Any descendant component rendered here will be able to access the cascading value. -->
</CascadingValue>
В компонентах-потомках можно получить доступ к каскадным значениям, используя элементы компонента и обозначая их атрибутом [CascadingParameter].
<h2>Deal: @DealName</h2>
@code {
[CascadingParameter(Name="DealName")]
private string DealName { get; set; }
}
Таким образом, в этом примере тег <h2> имеет содержимое Deal: Throwback Thursday, поскольку компонент-предок задает каскадное значение.
Note
Что касается параметров компонента, то можно передавать объекты в виде каскадных параметров, если у вас есть более сложные требования.
В предыдущем примере Name атрибут в родительском элементе определяет каскадное значение, которое соответствует Name значению в атрибуте [CascadingParameter] . При необходимости можно опустить эти имена, в этом случае атрибуты сопоставляются по типу. Пропуск имени работает хорошо, если у вас есть только один параметр этого типа. Если вы хотите каскадировать два разных строковых значения, необходимо использовать имена параметров, чтобы избежать неоднозначности.
Обмен сведениями с использованием AppState
Другим подходом к совместному использованию информации между различными компонентами является использование шаблона AppState. Вы создаете класс, определяющий свойства, которые вы хотите хранить, и регистрируете его в качестве службы с областью действия. В любом компоненте, где требуется задать или использовать значения AppState, вы внедряете службу, а затем можете получить доступ к его свойствам. В отличие от параметров компонента и каскадных параметров значения в AppState доступны всем компонентам в приложении, даже компонентам, которые не являются дочерними компонентами компонента, хранимого значением.
Например, рассмотрим этот класс, который сохраняет значение о продажах:
public class PizzaSalesState
{
public int PizzasSoldToday { get; set; }
}
Вы добавите класс в качестве службы с областью действия в файл Program.cs:
...
// Add services to the container
builder.Services.AddRazorPages();
builder.Services.AddServerSideBlazor();
// Add the AppState class
builder.Services.AddScoped<PizzaSalesState>();
...
Теперь в любом компоненте, где требуется задать или получить значения AppState, можно внедрить класс, а затем получить доступ к свойствам:
@page "/"
@inject PizzaSalesState SalesState
<h1>Welcome to Blazing Pizzas</h1>
<p>Today, we've sold this many pizzas: @SalesState.PizzasSoldToday</p>
<button @onclick="IncrementSales">Buy a Pizza</button>
@code {
private void IncrementSales()
{
SalesState.PizzasSoldToday++;
}
}
Note
Этот код реализует счётчик, который увеличивается, когда пользователь выбирает кнопку, как в примере из руководства по Blazor - Создание вашего первого приложения Blazor. Разница заключается в том, что в этом случае мы храним значение счетчика в службе с областью действия AppState. Класс служб с областью действия позволяет сохранять количество нагрузок страниц, а другие пользователи могут видеть его.
В следующем модуле вы попробуете сами!