Содержание
Компоненты Blazor имеют четко определенный жизненный цикл. Жизненный цикл компонента можно использовать для инициализации состояния компонента и/или реализации расширенного поведения компонентов. Компонент обрабатывает события своего жизненного цикла в наборе синхронных и асинхронных методов. Эти методы, при желании, можно переопределить для выполнения дополнительных операций с компонентом.
Методы жизненного цикла компонентов Blazor
OnInitialized
OnInitialized и OnInitializedAsync используются для инициализации компонента. Обычно компонент инициализируется после первого рендеринга. После того, как компонент инициализирован, он может быть отрендерен несколько раз, прежде чем в конечном итоге будет уничтожен. protected override void OnInitialized() { ... }
protected override async Task OnInitializedAsync() { await ... }
Например, у нас в приложении используется компонент, который выводит на экран сведения о человеке:
@page "/view-person"
@using MyApp.Data;
<h3>Person</h3>
<p>Имя: @person.Name</p>
<p>Возраст: @person.Age</p>
<p>Пол: @person.Gender</p>
@code {
Person person;
}
При попытке обращения к такому компоненту мы неизбежно получим исключение:
person было null.
В данном случае, мы могли бы поступить, например, так:
@code {
Person person = new() { Name = "Вася Пупкин", Age = 18, Gender = "Мужской" };
}
то есть сразу создать и инициализировать объект типа Person какими-то значениями по умолчанию. Это самый простой случай. Но, возможно, что по логике нашего приложения мы должны инициализировать объект, например, данными из базы данных. В этом случае как раз было бы удобным использовать метод OnInitialized (или его асинхронную версию OnInitializedAsync). В нашем примере это можно было бы сделать, переопределив метод:
@page "/view-person"
@using MyApp.Data;
<h3>Person</h3>
<p>Имя: @person.Name</p>
<p>Возраст: @person.Age</p>
<p>Пол: @person.Gender</p>
@code {
Person person;
protected override void OnInitialized()
{
person = new()
{
Name = "Вася Пупкин",
Age = 18,
Gender = "Мужской"
};
}
}
OnParametersSet
Методы OnParametersSet и OnParametersSetAsync вызываются, когда компонент получает значения параметров от своего родителя и значение присваивается свойствам. Эти методы выполняются после инициализации компонента и при каждом рендеринге компонента.
protected override void OnParametersSet() { ... }
protected override async Task OnParametersSetAsync() { await ... }
Эти методы выполняются также и в том случае, если родительский компонент не передает никаких параметров компоненту. Проверить это легко, если переопределить в нашем компоненте метод OnParametersSet следующим образом:
protected override void OnParametersSet()
{
Console.WriteLine("OnParametersSet()");
}
запустить приложение Blazor Server и загрузить компонент. В консоли мы увидим, что метод OnParametersSet был выполнен, несмотря на то, что мы не передавали этому компоненту никаких параметров:
В этом методе мы можем проводить какие-либо дополнительные манипуляции с переданными данными. Например, родительский компонент в качестве параметра может передать id элемента в базе данных, а в методе OnParametersSet нашего компонента мы можем получить данные из БД.
OnAfterRender
Методы OnAfterRender и OnAfterRenderAsync вызываются после завершения визуализации компонента. На этом этапе заполняются ссылки на элементы и компоненты. При выполнении этого метода пользователь может выполнять какие-либо действия в браузере. Методы OnAfterRender и OnAfterRenderAsync не вызываются при предварительном рендеринге на сервере. Параметр firstRender имеет значение true при первом рендеринге компонента, в противном случае его значение равно false.
protected override void OnAfterRender(bool firstRender)
{
if (firstRender)
{
...
}
}
protected override async Task OnAfterRenderAsync(bool firstRender)
{
if (firstRender)
{
await ...
}
}
Чтобы продемонстрировать когда параметр firstRender меняет свое значение с true на false допишем наш компонент следующим образом:
@page "/view-person"
@using MyApp.Data;
<h3>Person</h3>
<p>Имя: @person.Name</p>
<p>Возраст: @person.Age</p>
<p>Пол: @person.Gender</p>
<button @onclick="OnClick">Изменить Person</button>
@code {
Person person = new()
{
Name = "Вася Пупкин",
Age = 18,
Gender = "Мужской"
};
private void OnClick()
{
person.Name = "Петя";
person.Age = 15;
person.Gender = "мужской";
}
protected override void OnInitialized()
{
Console.WriteLine("OnInitialized()");
}
protected override void OnParametersSet()
{
Console.WriteLine("OnParametersSet()");
}
protected override void OnAfterRender(bool firstRender)
{
if (firstRender)
Console.WriteLine("OnAfterRender(firstRender = true)");
else
Console.WriteLine("OnAfterRender(firstRender = false)");
}
}
Здесь мы добавили кнопку клик по которой приводит к изменению значений свойств объекта person. Теперь можно запустить приложение, перейти к компоненту и увидеть следующий вывод в консоли:
OnParametersSet()
OnAfterRender(firstRender = true)
Если мы просто обновим страницу в браузере, то вывод консоли не изменится — firstRender также будет равен true, однако, если мы нажмем на кнопку несколько раз, то получим уже следующий вывод консоли:
OnAfterRender(firstRender = true)
OnAfterRender(firstRender = false)
OnAfterRender(firstRender = false)
OnAfterRender(firstRender = false)
OnAfterRender(firstRender = false)
в данном случае, кнопка была нажата четыре раза — компонент был перерисован также четырежды.
Интерфейс IDisposable
Компоненты Blazor могут реализовать интерфейс IDisposable для удаления ресурсов, когда компонент удален из пользовательского интерфейса. Для этого необходимо воспользоваться директивой @implements, например так:
@page "/view-person"
@using MyApp.Data;
@implements IDisposable;
.....
@code {
.....
public void Dispose()
{
Console.WriteLine("Dispose()");
}
}
Итого
Компоненты Blazor имеют четко определенный жизненный цикл, воздействовать на который мы можем переопределением методов жизненного цикла и реализацией интерфейса IDisposable. Порядок выполнение методов от инициализации компонента до его удаления из интерфейса следующий: OnInitialized() —> OnParametersSet() —> OnAfterRender(firstRender = true) —> OnAfterRender(firstRender = false) —> ….. OnAfterRender(firstRender = false) —> Dispose().
