Обработка событий компонентов Razor

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

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

Посмотрим ещё раз на обработчик события Click у кнопки компонента Counter в шаблонном приложении Blazor Hybrid:

Чтобы передавать события между родительскими и дочерними компонентами, применяется специальный тип — структура EventCallback, которая представлена в двух формах:

  • EventCallback
  • EventCallback<T>

В нашем случае использована вторая форма этой структуры — EventCallback<MouseEventArgs>. Если используется такой вид структуры для передачи событий, то обработчик события может принимать аргументы события. Например, в прошлой части мы использовали объект типа MouseEventArgs, чтобы определить какой действие необходимо выполнить — добавить или вычесть единицу из значений счётчика.

По сути, html-элемент button — это дочерний компонент нашего компонента Razor (в данном случае, компонента Counter). Поэтому ничто нам не мешает применить точно такой же подход к обработки событий непосредственно между компонентами Razor. Чтобы определить в компоненте Razor какое-либо событие, мы должны создать параметр компонента с типом EventCallback или EventCallback<T>, а для обработки этого события в родительском компоненте назначить параметру обработчик.

Обработка событий компонентов Razor

Использование EventCallback

Этот тип применяется, если нашему обработчику события не требуются никакие дополнительные сведения о событии.  Создадим новое приложение Blazor Hybrid и изменим код компонента Counter следующим образом:

@page "/counter"

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

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

Теперь перейдем в файл Home.razor и изменим его код:

@page "/"

<h1>Hello, world!</h1>

<p>Значение счётчика: @counter</p>
<Counter OnClick="IncCounter"></Counter>

@code{
    int counter = 0;
    private void IncCounter()
    {
        counter++;
    }
}

У компонента Counter мы создали событие OnClick:

[Parameter]
public EventCallback OnClick { get; set; }

Далее, мы добавили компонент Counter на страницу Home, то есть Counter у нас стал дочерним компонентов для Home и назначили компоненту обработчик события:

<Counter OnClick="IncCounter"></Counter>
@code{
    int counter = 0;
    private void IncCounter()
    {
        counter++;
    }
}

Теперь можно запустить приложение и убедиться, что на главной странице при клике по кнопке значение счётчика увеличивается на 1.

Здесь мы фактически вынесли логику компонента во вне. Давайте немного перепишем компонент Counter, а заодно посмотрим на ещё один вариант использования собственных событий компонентов Razor. Перепишем код компонента следующим образом:

@page "/counter"

<p role="status">Current count: @currentCount</p>
<button class="btn btn-primary" @onclick="IncrementCount">Click me</button>

@code {
    private int currentCount = 0;

    [Parameter]    
    public EventCallback OnFullCounter { get; set; }

    private async Task IncrementCount()
    {
        if (currentCount == 10)
        {
            await OnFullCounter.InvokeAsync();
        }
        else
            currentCount++;
    }
}

Здесь мы, по сути, вернули работу Counter к первоначальному виду. Но, при этом, объявили новое событие:

[Parameter]    
public EventCallback OnFullCounter { get; set; }

Обратите внимание, как вызывается обработчик этого события:

OnFullCounter.InvokeAsync();

Здесь мы вызываем метод InvokeAsync() у EventCallback. Этот метод выполняет делегат, ассоциированный с событием.  В нашем случае, как только значение счётчика достигнет 10, будет вызываться обработчик события. Теперь изменим код Home.razor следующим образом:

@page "/"

<h1>Hello, world!</h1>

@if (showAlert)
{
    <div class="alert alert-danger" role="alert">
        Значение счётчика достигло максимального значения
    </div> 
}
<br />

<Counter OnFullCounter="FullCounter"></Counter>

@code{

    bool showAlert = false;

    private void FullCounter()
    {
        showAlert = true;
    }
}

Всё, что делает наш обработчик события — это меняет значение у showAlert с false на true. В разметке компонента showAlert используется для определения того, необходимо ли показывать сообщение пользователю:

@if (showAlert)
{
    <div class="alert alert-danger" role="alert">
        Значение счётчика достигло максимального значения
    </div> 
}

Теперь запустим приложение и прокликаем кнопку «Click me» десять раз. На одиннадцатый клик сработает обработчик события и мы увидим вот такое сообщение:

И раз уж мы затронули тему использования метода InvokeAsync() , то теперь можно перейти к рассмотрению следующего момента обработки событий в компонентах Razor — использованию типа EventCallback<T>.

Использование EventCallback<T>

Этот тип стоит использовать в том случае, если обработчик события должен получать какие-либо аргументы события. Например, перепишем код Counter с использованием EventCallback<T> следующим образом:

@page "/counter"

<p role="status">Current count: @currentCount</p>
<button class="btn btn-primary" @onclick="IncrementCount">Click me</button>

@code {
    private int currentCount = 0;

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

    private async Task IncrementCount()
    {
        if (currentCount == 10)
        {
            await OnFullCounter.InvokeAsync("Это сообщение компонента");
        }
        else
            currentCount++;
    }
}

Здесь наше событие использует уже тип EventCallback<string>, то есть обработчик события может принимать в качестве аргумента строку. При вызове обработчика события мы воспользовались второй версией метода InvokeAsync():

public System.Threading.Tasks.Task InvokeAsync (object? arg);

В качестве параметров этот метод принимает некий объект — аргумент события. И при вызове обработчика мы это аргумент передаем:

await OnFullCounter.InvokeAsync("Это сообщение компонента");

Теперь перейдем в файл Home.razor и немного изменим его код:

@page "/"

<h1>Hello, world!</h1>

@if (showAlert)
{
    <div class="alert alert-danger" role="alert">
        @errorMessage
    </div> 
}
<br />

<Counter OnFullCounter="FullCounter"></Counter>

@code{
    string errorMessage = "Значение счётчика достигло максимального значения";
    bool showAlert = false;

    private void FullCounter(string message)
    {
        if (string.IsNullOrEmpty(message) == false)
            errorMessage = message;
        showAlert = true;
    }
}

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

if (string.IsNullOrEmpty(message) == false)
    errorMessage = message;

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

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

Итого

Для обработки событий компонентов Razor используются типы EventCallback и EventCallback<T>. Типизированный вариант EventCallback используется в том случае, если обработчик события может получать дополнительные аргументы.

Подписаться
Уведомить о
guest
0 Комментарий
Старые
Новые Популярные
Межтекстовые Отзывы
Посмотреть все комментарии