Содержание
Компоненты 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()
.