Примечание
Для доступа к этой странице требуется авторизация. Вы можете попробовать войти или изменить каталоги.
Для доступа к этой странице требуется авторизация. Вы можете попробовать изменить каталоги.
Примечание.
Это не последняя версия этой статьи. В текущем выпуске см статью о версии .NET 9.
Предупреждение
Эта версия ASP.NET Core больше не поддерживается. Дополнительные сведения см. в политике поддержки .NET и .NET Core. В текущем релизе см. версию этой статьи .NET 9.
Внимание
Эта информация относится к предварительному выпуску продукта, который может быть существенно изменен до его коммерческого выпуска. Майкрософт не предоставляет никаких гарантий, явных или подразумеваемых, относительно приведенных здесь сведений.
Для текущей версии смотрите статью о версии .NET 9.
В этой статье приведены сведения о функциях обработки событий Blazor, включая типы аргументов событий, обратные вызовы событий и управление событиями браузера по умолчанию.
Делегирование обработчиков событий
Укажите обработчики событий делегата в разметке компонента Razor с помощью синтаксиса @on{DOM EVENT}="{DELEGATE}"
Razor:
- Заполнитель
{DOM EVENT}
— это событие DOM (например,click
). - Заполнитель
{DELEGATE}
является обработчиком событий делегата C#.
Для обработки событий:
- Обработчики событий делегата в Blazor Web App вызываются только в компонентах, которые принимают интерактивный режим визуализации. В примерах в этой статье предполагается, что в корневом компоненте приложения, как правило, компоненте
App
, приложение глобально использует интерактивный режим отрисовки. Дополнительные сведения см. в ASP.NET Core Blazor режимах отрисовки. - Обработчики событий делегата, возвращающие асинхронно Task (
async Task
), поддерживаются Blazor, а также принимаются примерами в документации Blazor Web App и Blazor WebAssembly. - Обработчики событий делегата автоматически инициируют рендеринг пользовательского интерфейса, поэтому не требуется вручную вызывать
StateHasChanged
. - Исключения заносятся в журнал.
- Обработчики событий асинхронного делегата, возвращающие (Task
async Task
) поддерживаются Blazor и принимаются Blazor ServerBlazor WebAssembly примерами документации. - Обработчики событий делегата автоматически инициируют отрисовку пользовательского интерфейса, поэтому не требуется вручную вызывать метод
StateHasChanged
. - Исключения заносятся в журнал.
Следующий код:
- Вызывает метод
UpdateHeading
, когда в пользовательском интерфейсе выбрана кнопка. - Вызывает метод
CheckChanged
, когда в пользовательском интерфейсе установлен или снят флажок.
EventHandler1.razor
:
@page "/event-handler-1"
<PageTitle>Event Handler 1</PageTitle>
<h1>Event Handler Example 1</h1>
<h2>@headingValue</h2>
<p>
<button @onclick="UpdateHeading">
Update heading
</button>
</p>
<p>
<label>
<input type="checkbox" @onchange="CheckChanged" />
@checkedMessage
</label>
</p>
@code {
private string headingValue = "Initial heading";
private string checkedMessage = "Not changed yet";
private void UpdateHeading() => headingValue = $"New heading ({DateTime.Now})";
private void CheckChanged() => checkedMessage = $"Last change {DateTime.Now}";
}
EventHandler1.razor
:
@page "/event-handler-1"
<PageTitle>Event Handler 1</PageTitle>
<h1>Event Handler Example 1</h1>
<h2>@headingValue</h2>
<p>
<button @onclick="UpdateHeading">
Update heading
</button>
</p>
<p>
<label>
<input type="checkbox" @onchange="CheckChanged" />
@checkedMessage
</label>
</p>
@code {
private string headingValue = "Initial heading";
private string checkedMessage = "Not changed yet";
private void UpdateHeading() => headingValue = $"New heading ({DateTime.Now})";
private void CheckChanged() => checkedMessage = $"Last change {DateTime.Now}";
}
EventHandlerExample1.razor
:
@page "/event-handler-1"
<h1>@headingValue</h1>
<p>
<button @onclick="UpdateHeading">
Update heading
</button>
</p>
<p>
<label>
<input type="checkbox" @onchange="CheckChanged" />
@checkedMessage
</label>
</p>
@code {
private string headingValue = "Initial heading";
private string checkedMessage = "Not changed yet";
private void UpdateHeading()
{
headingValue = $"New heading ({DateTime.Now})";
}
private void CheckChanged()
{
checkedMessage = $"Last changed at {DateTime.Now}";
}
}
EventHandlerExample1.razor
:
@page "/event-handler-1"
<h1>@headingValue</h1>
<p>
<button @onclick="UpdateHeading">
Update heading
</button>
</p>
<p>
<label>
<input type="checkbox" @onchange="CheckChanged" />
@checkedMessage
</label>
</p>
@code {
private string headingValue = "Initial heading";
private string checkedMessage = "Not changed yet";
private void UpdateHeading()
{
headingValue = $"New heading ({DateTime.Now})";
}
private void CheckChanged()
{
checkedMessage = $"Last changed at {DateTime.Now}";
}
}
EventHandlerExample1.razor
:
@page "/event-handler-1"
<h1>@headingValue</h1>
<p>
<button @onclick="UpdateHeading">
Update heading
</button>
</p>
<p>
<label>
<input type="checkbox" @onchange="CheckChanged" />
@checkedMessage
</label>
</p>
@code {
private string headingValue = "Initial heading";
private string checkedMessage = "Not changed yet";
private void UpdateHeading()
{
headingValue = $"New heading ({DateTime.Now})";
}
private void CheckChanged()
{
checkedMessage = $"Last changed at {DateTime.Now}";
}
}
EventHandlerExample1.razor
:
@page "/event-handler-1"
<h1>@headingValue</h1>
<p>
<button @onclick="UpdateHeading">
Update heading
</button>
</p>
<p>
<label>
<input type="checkbox" @onchange="CheckChanged" />
@checkedMessage
</label>
</p>
@code {
private string headingValue = "Initial heading";
private string checkedMessage = "Not changed yet";
private void UpdateHeading()
{
headingValue = $"New heading ({DateTime.Now})";
}
private void CheckChanged()
{
checkedMessage = $"Last changed at {DateTime.Now}";
}
}
В следующем примере UpdateHeading
:
- Вызывается асинхронно при выборе кнопки.
- Ожидает две секунды перед обновлением заголовка.
EventHandler2.razor
:
@page "/event-handler-2"
<PageTitle>Event Handler 2</PageTitle>
<h1>Event Handler Example 2</h1>
<h2>@headingValue</h2>
<p>
<button @onclick="UpdateHeading">
Update heading
</button>
</p>
@code {
private string headingValue = "Initial heading";
private async Task UpdateHeading()
{
await Task.Delay(2000);
headingValue = $"New heading ({DateTime.Now})";
}
}
EventHandler2.razor
:
@page "/event-handler-2"
<PageTitle>Event Handler 2</PageTitle>
<h1>Event Handler Example 2</h1>
<h2>@headingValue</h2>
<p>
<button @onclick="UpdateHeading">
Update heading
</button>
</p>
@code {
private string headingValue = "Initial heading";
private async Task UpdateHeading()
{
await Task.Delay(2000);
headingValue = $"New heading ({DateTime.Now})";
}
}
EventHandlerExample2.razor
:
@page "/event-handler-2"
<h1>@headingValue</h1>
<p>
<button @onclick="UpdateHeading">
Update heading
</button>
</p>
@code {
private string headingValue = "Initial heading";
private async Task UpdateHeading()
{
await Task.Delay(2000);
headingValue = $"New heading ({DateTime.Now})";
}
}
EventHandlerExample2.razor
:
@page "/event-handler-2"
<h1>@headingValue</h1>
<p>
<button @onclick="UpdateHeading">
Update heading
</button>
</p>
@code {
private string headingValue = "Initial heading";
private async Task UpdateHeading()
{
await Task.Delay(2000);
headingValue = $"New heading ({DateTime.Now})";
}
}
EventHandlerExample2.razor
:
@page "/event-handler-2"
<h1>@headingValue</h1>
<p>
<button @onclick="UpdateHeading">
Update heading
</button>
</p>
@code {
private string headingValue = "Initial heading";
private async Task UpdateHeading()
{
await Task.Delay(2000);
headingValue = $"New heading ({DateTime.Now})";
}
}
EventHandlerExample2.razor
:
@page "/event-handler-2"
<h1>@headingValue</h1>
<p>
<button @onclick="UpdateHeading">
Update heading
</button>
</p>
@code {
private string headingValue = "Initial heading";
private async Task UpdateHeading()
{
await Task.Delay(2000);
headingValue = $"New heading ({DateTime.Now})";
}
}
Встроенные аргументы событий
Для событий, которые поддерживают тип аргумента события, указание параметра события в определении метода события требуется только в том случае, если тип события используется в методе. В следующем примере MouseEventArgs используется в методе ReportPointerLocation
для задания текста сообщения, которое информирует о координатах мыши, когда пользователь нажимает кнопку в пользовательском интерфейсе.
EventHandler3.razor
:
@page "/event-handler-3"
<PageTitle>Event Handler 3</PageTitle>
<h1>Event Handler Example 3</h1>
@for (var i = 0; i < 4; i++)
{
<p>
<button @onclick="ReportPointerLocation">
Where's my mouse pointer for this button?
</button>
</p>
}
<p>@mousePointerMessage</p>
@code {
private string? mousePointerMessage;
private void ReportPointerLocation(MouseEventArgs e) =>
mousePointerMessage = $"Mouse coordinates: {e.ScreenX}:{e.ScreenY}";
}
EventHandler3.razor
:
@page "/event-handler-3"
<PageTitle>Event Handler 3</PageTitle>
<h1>Event Handler Example 3</h1>
@for (var i = 0; i < 4; i++)
{
<p>
<button @onclick="ReportPointerLocation">
Where's my mouse pointer for this button?
</button>
</p>
}
<p>@mousePointerMessage</p>
@code {
private string? mousePointerMessage;
private void ReportPointerLocation(MouseEventArgs e) =>
mousePointerMessage = $"Mouse coordinates: {e.ScreenX}:{e.ScreenY}";
}
EventHandlerExample3.razor
:
@page "/event-handler-example-3"
@for (var i = 0; i < 4; i++)
{
<p>
<button @onclick="ReportPointerLocation">
Where's my mouse pointer for this button?
</button>
</p>
}
<p>@mousePointerMessage</p>
@code {
private string? mousePointerMessage;
private void ReportPointerLocation(MouseEventArgs e)
{
mousePointerMessage = $"Mouse coordinates: {e.ScreenX}:{e.ScreenY}";
}
}
EventHandlerExample3.razor
:
@page "/event-handler-example-3"
@for (var i = 0; i < 4; i++)
{
<p>
<button @onclick="ReportPointerLocation">
Where's my mouse pointer for this button?
</button>
</p>
}
<p>@mousePointerMessage</p>
@code {
private string? mousePointerMessage;
private void ReportPointerLocation(MouseEventArgs e)
{
mousePointerMessage = $"Mouse coordinates: {e.ScreenX}:{e.ScreenY}";
}
}
EventHandlerExample3.razor
:
@page "/event-handler-example-3"
@for (var i = 0; i < 4; i++)
{
<p>
<button @onclick="ReportPointerLocation">
Where's my mouse pointer for this button?
</button>
</p>
}
<p>@mousePointerMessage</p>
@code {
private string mousePointerMessage;
private void ReportPointerLocation(MouseEventArgs e)
{
mousePointerMessage = $"Mouse coordinates: {e.ScreenX}:{e.ScreenY}";
}
}
EventHandlerExample3.razor
:
@page "/event-handler-example-3"
@for (var i = 0; i < 4; i++)
{
<p>
<button @onclick="ReportPointerLocation">
Where's my mouse pointer for this button?
</button>
</p>
}
<p>@mousePointerMessage</p>
@code {
private string mousePointerMessage;
private void ReportPointerLocation(MouseEventArgs e)
{
mousePointerMessage = $"Mouse coordinates: {e.ScreenX}:{e.ScreenY}";
}
}
Поддерживаемые параметры EventArgs приведены в следующей таблице.
Мероприятие | Класс | Заметки DOM |
---|---|---|
Буфер обмена | ClipboardEventArgs | |
Перетаскивание | DragEventArgs |
DataTransfer и DataTransferItem содержат данные перетаскиваемого элемента. Реализуйте перетаскивание в приложениях Blazor с помощью взаимодействия JSJS с API перетаскивания для HTML. |
Ошибка | ErrorEventArgs | |
Мероприятие | EventArgs | EventHandlers содержит атрибуты для настройки сопоставлений между именами событий и типами аргументов событий. |
Фокус | FocusEventArgs | Не включает поддержку relatedTarget . |
Ввод | ChangeEventArgs | |
Клавиатура | KeyboardEventArgs | |
Мышь | MouseEventArgs | |
указатель мыши | PointerEventArgs | |
Колесо мыши | WheelEventArgs | |
Ход выполнения | ProgressEventArgs | |
Сенсорный ввод | TouchEventArgs | TouchPoint представляет одну точку касания на устройстве с сенсорным вводом. |
Дополнительные сведения см. на следующих ресурсах:
Классы
EventArgs
в справочных материалах по ASP.NET Core (ветвь dotnet/aspnetcoremain
).Примечание.
В документации ссылки на справочные материалы по .NET обычно ведут на основную ветвь репозитория, представляющую текущую разработку для следующего выпуска .NET. Чтобы выбрать тег для определенного выпуска, используйте раскрывающееся меню «Переключение ветвей или тегов». Дополнительные сведения см. в статье Выбор тега версии исходного кода ASP.NET Core (dotnet/AspNetCore.Docs #26205).
EventHandlers содержит атрибуты для настройки сопоставлений между именами событий и типами аргументов событий.
Аргументы пользовательских событий
Blazor поддерживает аргументы пользовательских событий, которые позволяют передавать произвольные данные в обработчики событий .NET с пользовательскими событиями.
Общая конфигурация
Для включения пользовательских событий с пользовательскими аргументами обычно выполняются следующие действия.
В JavaScript определите функцию для создания объекта аргумента пользовательского события из исходного события:
function eventArgsCreator(event) {
return {
customProperty1: 'any value for property 1',
customProperty2: event.srcElement.id
};
}
Параметр event
является событием DOM.
Зарегистрируйте настраиваемое событие с помощью указанного обработчика в инициализаторе JavaScript. Укажите соответствующее имя события браузера для browserEventName
, которое в примере, приведенном в этом разделе, предназначено для click
при выборе кнопки в пользовательском интерфейсе.
wwwroot/{PACKAGE ID/ASSEMBLY NAME}.lib.module.js
(заполнитель {PACKAGE ID/ASSEMBLY NAME}
— это идентификатор пакета или имя сборки приложения):
Для Blazor Web App:
export function afterWebStarted(blazor) {
blazor.registerCustomEventType('customevent', {
browserEventName: 'click',
createEventArgs: eventArgsCreator
});
}
Для приложения Blazor Server или Blazor WebAssembly:
export function afterStarted(blazor) {
blazor.registerCustomEventType('customevent', {
browserEventName: 'click',
createEventArgs: eventArgsCreator
});
}
Вызов registerCustomEventType
выполняется в скрипте только один раз для каждого события.
Для вызова registerCustomEventType
используйте параметр blazor
(строчные буквы b
), предоставленный событием начала Blazor. Хотя регистрация допустима при использовании Blazor
объекта (в верхнем регистре B
), предпочтительный подход — использовать параметр.
Имя настраиваемого события в customevent
предыдущем примере не должно совпадать с зарезервированным Blazor именем события. Зарезервированные имена можно найти в справочной документации Blazor фреймворка (см. вызовы функции registerBuiltInEventType
).
Примечание.
По ссылкам в документации на справочные материалы по .NET обычно загружается ветвь репозитория по умолчанию, которая представляет текущую разработку для следующего выпуска .NET. Чтобы выбрать тег для определенного выпуска, используйте раскрывающийся список Switch branches or tags (Переключение ветвей или тегов). Дополнительные сведения см. в статье Выбор тега версии исходного кода ASP.NET Core (dotnet/AspNetCore.Docs #26205).
Определите класс для аргументов события:
namespace BlazorSample.CustomEvents;
public class CustomEventArgs : EventArgs
{
public string? CustomProperty1 {get; set;}
public string? CustomProperty2 {get; set;}
}
Подключите настраиваемое событие к аргументам события, добавив аннотацию [EventHandler]
атрибута для этого события.
- Чтобы компилятор найти
[EventHandler]
класс, он должен быть помещен в файл класса C# (.cs
), что делает его обычным классом верхнего уровня. - Пометьте класс
public
. - Классу не нужны члены.
- Класс должен называться "
EventHandlers
" для обнаружения компилятором Razor . - Поместите класс под пространством имен, определенным для приложения.
- Импортируйте пространство имен в компонент Razor (
.razor
), где используется событие.
using Microsoft.AspNetCore.Components;
namespace BlazorSample.CustomEvents;
[EventHandler("oncustomevent", typeof(CustomEventArgs),
enableStopPropagation: true, enablePreventDefault: true)]
public static class EventHandlers
{
}
регистрировали обработчик событий в одном или нескольких элементах HTML; Получите доступ к данным, переданным из JavaScript, в методе обработчика делегата:
@using BlazorSample.CustomEvents
<button id="buttonId" @oncustomevent="HandleCustomEvent">Handle</button>
@if (!string.IsNullOrEmpty(propVal1) && !string.IsNullOrEmpty(propVal2))
{
<ul>
<li>propVal1: @propVal1</li>
<li>propVal2: @propVal2</li>
</ul>
}
@code
{
private string? propVal1;
private string? propVal2;
private void HandleCustomEvent(CustomEventArgs eventArgs)
{
propVal1 = eventArgs.CustomProperty1;
propVal2 = eventArgs.CustomProperty2;
}
}
Если @oncustomevent
не распознает атрибут , убедитесь, что компонент или файл _Imports.razor
содержит инструкцию @using
для пространства имен, содержащего класс EventHandler
.
При каждом запуске пользовательского события в модели DOM обработчик событий вызывается с данными, передаваемыми из JavaScript.
Если вы пытаетесь запустить пользовательское событие, необходимо включить bubbles
, задав для него значение true
. В противном случае событие не достигает обработчика Blazor для обработки в пользовательском [EventHandler]
классе атрибутов C#. Дополнительные сведения см. в MDN Web Docs: Всплытие событий.
Пример пользовательского события вставки в буфер обмена
В следующем примере описывается получение настраиваемого события вставки из буфера обмена, включающего время вставки и вставленный текст пользователя.
Объявите пользовательское имя (oncustompaste
) для события и класса .NET (CustomPasteEventArgs
) для хранения аргументов события для этого события:
CustomEvents.cs
:
using Microsoft.AspNetCore.Components;
namespace BlazorSample.CustomEvents;
[EventHandler("oncustompaste", typeof(CustomPasteEventArgs),
enableStopPropagation: true, enablePreventDefault: true)]
public static class EventHandlers
{
}
public class CustomPasteEventArgs : EventArgs
{
public DateTime EventTimestamp { get; set; }
public string? PastedData { get; set; }
}
Добавьте код JavaScript для предоставления данных для подкласса EventArgs с предварительным обработчиком в инициализаторе JavaScript. В следующем примере выполняется обработка только текста, но для взаимодействия с пользователями, вставляющими другие типы данных, например изображения, можно использовать произвольные API JavaScript.
wwwroot/{PACKAGE ID/ASSEMBLY NAME}.lib.module.js
:
Для Blazor Web App:
export function afterWebStarted(blazor) {
blazor.registerCustomEventType('custompaste', {
browserEventName: 'paste',
createEventArgs: event => {
return {
eventTimestamp: new Date(),
pastedData: event.clipboardData.getData('text')
};
}
});
}
Для Blazor Server или Blazor WebAssembly приложения:
export function afterStarted(blazor) {
blazor.registerCustomEventType('custompaste', {
browserEventName: 'paste',
createEventArgs: event => {
return {
eventTimestamp: new Date(),
pastedData: event.clipboardData.getData('text')
};
}
});
}
В предыдущем примере заполнитель {PACKAGE ID/ASSEMBLY NAME}
в имени файла представляет собой идентификатор пакета или имя сборки приложения.
Примечание.
Для вызова registerCustomEventType
используйте параметр blazor
(нижний регистр b
), предоставленного начальным событием Blazor. Хотя регистрация допустима при использовании Blazor
объекта (в верхнем регистре B
), предпочтительный подход — использовать параметр.
Приведенный выше код указывает браузеру, что при возникновении нативного события paste
происходит следующее:
- вызвать событие
custompaste
. - Используйте пользовательскую логику для указания данных аргументов события:
- Для
eventTimestamp
создайте новую дату. - получить данные из буфера обмена в виде текста для
pastedData
. Дополнительные сведения см. в веб-документации MDN: ClipboardEvent.clipboardData.
- Для
Соглашения об именах событий отличаются в .NET и JavaScript:
- В .NET имена событий начинаются с префикса "
on
". - В JavaScript у имен событий нет префикса.
В компоненте Razor присоедините пользовательский обработчик к элементу.
CustomPasteArguments.razor
:
@page "/custom-paste-arguments"
@using BlazorSample.CustomEvents
<label>
Try pasting into the following text box:
<input @oncustompaste="HandleCustomPaste" />
</label>
<p>
@message
</p>
@code {
private string? message;
private void HandleCustomPaste(CustomPasteEventArgs eventArgs)
{
message = $"At {eventArgs.EventTimestamp.ToShortTimeString()}, " +
$"you pasted: {eventArgs.PastedData}";
}
}
Лямбда-выражения
Лямбда-выражения поддерживаются в качестве обработчика событий делегата.
EventHandler4.razor
:
@page "/event-handler-4"
<PageTitle>Event Handler 4</PageTitle>
<h1>Event Handler Example 4</h1>
<h2>@heading</h2>
<p>
<button @onclick="@(e => heading = "New heading!!!")">
Update heading
</button>
</p>
@code {
private string heading = "Initial heading";
}
EventHandler4.razor
:
@page "/event-handler-4"
<PageTitle>Event Handler 4</PageTitle>
<h1>Event Handler Example 4</h1>
<h2>@heading</h2>
<p>
<button @onclick="@(e => heading = "New heading!!!")">
Update heading
</button>
</p>
@code {
private string heading = "Initial heading";
}
EventHandlerExample4.razor
:
@page "/event-handler-example-4"
<h1>@heading</h1>
<p>
<button @onclick="@(e => heading = "New heading!!!")">
Update heading
</button>
</p>
@code {
private string heading = "Initial heading";
}
EventHandlerExample4.razor
:
@page "/event-handler-example-4"
<h1>@heading</h1>
<p>
<button @onclick="@(e => heading = "New heading!!!")">
Update heading
</button>
</p>
@code {
private string heading = "Initial heading";
}
EventHandlerExample4.razor
:
@page "/event-handler-example-4"
<h1>@heading</h1>
<p>
<button @onclick="@(e => heading = "New heading!!!")">
Update heading
</button>
</p>
@code {
private string heading = "Initial heading";
}
EventHandlerExample4.razor
:
@page "/event-handler-example-4"
<h1>@heading</h1>
<p>
<button @onclick="@(e => heading = "New heading!!!")">
Update heading
</button>
</p>
@code {
private string heading = "Initial heading";
}
Часто бывает удобно замыкать дополнительные значения с помощью параметров метода C#, например при переборе набора элементов. В следующем примере создаются три кнопки, каждая из которых вызывает UpdateHeading
и передает следующие данные:
- аргумент события (MouseEventArgs) в
e
; - Номер кнопки в
buttonNumber
.
EventHandler5.razor
:
@page "/event-handler-5"
<PageTitle>Event Handler 5</PageTitle>
<h1>Event Handler Example 5</h1>
<h2>@heading</h2>
@for (var i = 1; i < 4; i++)
{
var buttonNumber = i;
<p>
<button @onclick="@(e => UpdateHeading(e, buttonNumber))">
Button #@i
</button>
</p>
}
@code {
private string heading = "Select a button to learn its position";
private void UpdateHeading(MouseEventArgs e, int buttonNumber) =>
heading = $"Selected #{buttonNumber} at {e.ClientX}:{e.ClientY}";
}
EventHandler5.razor
:
@page "/event-handler-5"
<PageTitle>Event Handler 5</PageTitle>
<h1>Event Handler Example 5</h1>
<h2>@heading</h2>
@for (var i = 1; i < 4; i++)
{
var buttonNumber = i;
<p>
<button @onclick="@(e => UpdateHeading(e, buttonNumber))">
Button #@i
</button>
</p>
}
@code {
private string heading = "Select a button to learn its position";
private void UpdateHeading(MouseEventArgs e, int buttonNumber) =>
heading = $"Selected #{buttonNumber} at {e.ClientX}:{e.ClientY}";
}
EventHandlerExample5.razor
:
@page "/event-handler-example-5"
<h1>@heading</h1>
@for (var i = 1; i < 4; i++)
{
var buttonNumber = i;
<p>
<button @onclick="@(e => UpdateHeading(e, buttonNumber))">
Button #@i
</button>
</p>
}
@code {
private string heading = "Select a button to learn its position";
private void UpdateHeading(MouseEventArgs e, int buttonNumber)
{
heading = $"Selected #{buttonNumber} at {e.ClientX}:{e.ClientY}";
}
}
EventHandlerExample5.razor
:
@page "/event-handler-example-5"
<h1>@heading</h1>
@for (var i = 1; i < 4; i++)
{
var buttonNumber = i;
<p>
<button @onclick="@(e => UpdateHeading(e, buttonNumber))">
Button #@i
</button>
</p>
}
@code {
private string heading = "Select a button to learn its position";
private void UpdateHeading(MouseEventArgs e, int buttonNumber)
{
heading = $"Selected #{buttonNumber} at {e.ClientX}:{e.ClientY}";
}
}
EventHandlerExample5.razor
:
@page "/event-handler-example-5"
<h1>@heading</h1>
@for (var i = 1; i < 4; i++)
{
var buttonNumber = i;
<p>
<button @onclick="@(e => UpdateHeading(e, buttonNumber))">
Button #@i
</button>
</p>
}
@code {
private string heading = "Select a button to learn its position";
private void UpdateHeading(MouseEventArgs e, int buttonNumber)
{
heading = $"Selected #{buttonNumber} at {e.ClientX}:{e.ClientY}";
}
}
EventHandlerExample5.razor
:
@page "/event-handler-example-5"
<h1>@heading</h1>
@for (var i = 1; i < 4; i++)
{
var buttonNumber = i;
<p>
<button @onclick="@(e => UpdateHeading(e, buttonNumber))">
Button #@i
</button>
</p>
}
@code {
private string heading = "Select a button to learn its position";
private void UpdateHeading(MouseEventArgs e, int buttonNumber)
{
heading = $"Selected #{buttonNumber} at {e.ClientX}:{e.ClientY}";
}
}
Создание большого количества делегатов событий в цикле может привести к ухудшению производительности отрисовки. Дополнительные рекомендации см. в статье Рекомендации по повышению производительности ASP.NET Core Blazor.
Избегайте использования переменной цикла непосредственно в лямбда-выражении, например i
в предыдущем for
примере цикла. В противном случае одна и та же переменная будет использоваться во всех лямбда-выражениях, в результате чего значение будет одинаковым во всех лямбда-выражениях. Сохраните значение переменной в локальной переменной. В предыдущем примере:
- Переменной цикла
i
присваивается значениеbuttonNumber
. -
buttonNumber
используется в лямбда-выражении.
В качестве альтернативы используйте цикл foreach
с Enumerable.Range, который не затронула предыдущая проблема.
@foreach (var buttonNumber in Enumerable.Range(1, 3))
{
<p>
<button @onclick="@(e => UpdateHeading(e, buttonNumber))">
Button #@buttonNumber
</button>
</p>
}
EventCallback
Распространенный сценарий с вложенными компонентами выполняет метод в родительском компоненте при возникновении события дочернего компонента. Событие onclick
, происходящее в дочернем компоненте, является распространённым случаем использования. Чтобы распространять события между компонентами, используйте EventCallback. Родительский компонент может назначить дочернему компоненту метод обратного вызова EventCallback.
Следующий компонент Child
демонстрирует, как обработчик кнопки onclick
настроен для получения делегата EventCallback из примера ParentComponent
.
EventCallback вводится с помощью MouseEventArgs, что подходит для события onclick
от периферийного устройства.
Child.razor
:
<p>
<button @onclick="OnClickCallback">
Trigger a Parent component method
</button>
</p>
@code {
[Parameter]
public string? Title { get; set; }
[Parameter]
public RenderFragment? ChildContent { get; set; }
[Parameter]
public EventCallback<MouseEventArgs> OnClickCallback { get; set; }
}
<p>
<button @onclick="OnClickCallback">
Trigger a Parent component method
</button>
</p>
@code {
[Parameter]
public string? Title { get; set; }
[Parameter]
public RenderFragment? ChildContent { get; set; }
[Parameter]
public EventCallback<MouseEventArgs> OnClickCallback { get; set; }
}
<p>
<button @onclick="OnClickCallback">
Trigger a Parent component method
</button>
</p>
@code {
[Parameter]
public string? Title { get; set; }
[Parameter]
public RenderFragment? ChildContent { get; set; }
[Parameter]
public EventCallback<MouseEventArgs> OnClickCallback { get; set; }
}
<p>
<button @onclick="OnClickCallback">
Trigger a Parent component method
</button>
</p>
@code {
[Parameter]
public string? Title { get; set; }
[Parameter]
public RenderFragment? ChildContent { get; set; }
[Parameter]
public EventCallback<MouseEventArgs> OnClickCallback { get; set; }
}
<p>
<button @onclick="OnClickCallback">
Trigger a Parent component method
</button>
</p>
@code {
[Parameter]
public string Title { get; set; }
[Parameter]
public RenderFragment ChildContent { get; set; }
[Parameter]
public EventCallback<MouseEventArgs> OnClickCallback { get; set; }
}
<p>
<button @onclick="OnClickCallback">
Trigger a Parent component method
</button>
</p>
@code {
[Parameter]
public string Title { get; set; }
[Parameter]
public RenderFragment ChildContent { get; set; }
[Parameter]
public EventCallback<MouseEventArgs> OnClickCallback { get; set; }
}
Родительский компонент задает EventCallback<TValue> дочернего компонента (OnClickCallback
) своему методу ShowMessage
.
ParentChild.razor
:
@page "/parent-child"
<PageTitle>Parent Child</PageTitle>
<h1>Parent Child Example</h1>
<Child Title="Panel Title from Parent" OnClickCallback="ShowMessage">
Content of the child component is supplied by the parent component.
</Child>
<p>@message</p>
@code {
private string? message;
private void ShowMessage(MouseEventArgs e) =>
message = $"Blaze a new trail with Blazor! ({e.ScreenX}:{e.ScreenY})";
}
ParentChild.razor
:
@page "/parent-child"
<PageTitle>Parent Child</PageTitle>
<h1>Parent Child Example</h1>
<Child Title="Panel Title from Parent" OnClickCallback="ShowMessage">
Content of the child component is supplied by the parent component.
</Child>
<p>@message</p>
@code {
private string? message;
private void ShowMessage(MouseEventArgs e) =>
message = $"Blaze a new trail with Blazor! ({e.ScreenX}:{e.ScreenY})";
}
Parent.razor
:
@page "/parent"
<h1>Parent-child example</h1>
<Child Title="Panel Title from Parent" OnClickCallback="ShowMessage">
Content of the child component is supplied by the parent component.
</Child>
<p>@message</p>
@code {
private string? message;
private void ShowMessage(MouseEventArgs e)
{
message = $"Blaze a new trail with Blazor! ({e.ScreenX}:{e.ScreenY})";
}
}
Parent.razor
:
@page "/parent"
<h1>Parent-child example</h1>
<Child Title="Panel Title from Parent" OnClickCallback="ShowMessage">
Content of the child component is supplied by the parent component.
</Child>
<p>@message</p>
@code {
private string? message;
private void ShowMessage(MouseEventArgs e)
{
message = $"Blaze a new trail with Blazor! ({e.ScreenX}:{e.ScreenY})";
}
}
Parent.razor
:
@page "/parent"
<h1>Parent-child example</h1>
<Child Title="Panel Title from Parent" OnClickCallback="ShowMessage">
Content of the child component is supplied by the parent component.
</Child>
<p>@message</p>
@code {
private string message;
private void ShowMessage(MouseEventArgs e)
{
message = $"Blaze a new trail with Blazor! ({e.ScreenX}:{e.ScreenY})";
}
}
Parent.razor
:
@page "/parent"
<h1>Parent-child example</h1>
<Child Title="Panel Title from Parent" OnClickCallback="ShowMessage">
Content of the child component is supplied by the parent component.
</Child>
<p>@message</p>
@code {
private string message;
private void ShowMessage(MouseEventArgs e)
{
message = $"Blaze a new trail with Blazor! ({e.ScreenX}:{e.ScreenY})";
}
}
При выборе кнопки в ChildComponent
:
- Вызывается метод
Parent
компонентаShowMessage
.message
обновляется и отображается в компонентеParent
. - Вызов
StateHasChanged
не требуется в методе обратного вызова (ShowMessage
). StateHasChanged вызывается автоматически для повторной отрисовки компонентаParent
, так же как и дочерние события запускают повторную отрисовку компонента в обработчиках событий, которые выполняются в дочернем элементе. Дополнительные сведения см. в статье Отрисовка компонентов Razor ASP.NET Core.
Используйте EventCallback и EventCallback<TValue> для обработки событий и параметров компонента привязки.
Предпочтительнее использовать строго типизированный EventCallback<TValue> вместо EventCallback. EventCallback<TValue> предоставляет расширенные отзывы об ошибках, если используется недопустимый тип, ориентируя пользователей компонента к правильной реализации. Как и в случае с другими обработчиками событий пользовательского интерфейса, указание параметра события является необязательным. Используйте EventCallback, если в обратный вызов не было передано значение.
EventCallback и EventCallback<TValue> позволяют асинхронные делегаты. Структура EventCallback слабо типизирована и позволяет передавать аргумент любого типа в InvokeAsync(Object)
. Структура EventCallback<TValue> строго типизирована и требует передачи аргумента T
в InvokeAsync(T)
, который можно привести к типу TValue
.
Вызовите EventCallback или EventCallback<TValue> с помощью InvokeAsync и дождитесь Task:
await OnClickCallback.InvokeAsync({ARGUMENT});
В предыдущем примере {ARGUMENT}
заполнитель является необязательным аргументом.
В следующем примере связи родитель-потомок демонстрируется техника.
Child2.razor
:
<h3>Child2 Component</h3>
<button @onclick="TriggerEvent">Click Me</button>
@code {
[Parameter]
public EventCallback<string> OnClickCallback { get; set; }
private async Task TriggerEvent()
{
await OnClickCallback.InvokeAsync("Blaze It!");
}
}
ParentChild2.razor
:
@page "/parent-child-2"
<PageTitle>Parent Child 2</PageTitle>
<h1>Parent Child 2 Example</h1>
<div>
<Child2 OnClickCallback="(value) => { message1 = value; }" />
@message1
</div>
<div>
<Child2 OnClickCallback=
"async (value) => { await Task.Delay(2000); message2 = value; }" />
@message2
</div>
@code {
private string message1 = string.Empty;
private string message2 = string.Empty;
}
Второе вхождение компонента Child2
демонстрирует асинхронный обратный вызов, а новое значение message2
назначается и с задержкой в две секунды отрисовывается.
Запрет действий по умолчанию
@on{DOM EVENT}:preventDefault
Используйте атрибут директивы, чтобы предотвратить действие по умолчанию для события, где {DOM EVENT}
заполнитель представляет собой событие DOM.
Если на устройстве ввода выбран ключ, а фокус находится на текстовом поле, то в браузере в текстовом поле обычно отображается символ ключа. В следующем примере поведение по умолчанию запрещено путем указания атрибута директивы @onkeydown:preventDefault
. Когда фокус находится на элементе <input>
, счетчик увеличивается при использовании сочетания клавиш SHIFT++. Символ +
не назначается значению элемента <input>
. Дополнительные сведения о keydown
см. в разделе о событии MDN Web Docs: Document: keydown
.
EventHandler6.razor
:
@page "/event-handler-6"
<PageTitle>Event Handler 6</PageTitle>
<h1>Event Handler Example 6</h1>
<p>For this example, give the <code><input></code> focus.</p>
<p>
<label>
Count of '+' key presses:
<input value="@count" @onkeydown="KeyHandler" @onkeydown:preventDefault />
</label>
</p>
@code {
private int count = 0;
private void KeyHandler(KeyboardEventArgs e)
{
if (e.Key == "+")
{
count++;
}
}
}
EventHandler6.razor
:
@page "/event-handler-6"
<PageTitle>Event Handler 6</PageTitle>
<h1>Event Handler Example 6</h1>
<p>For this example, give the <code><input></code> focus.</p>
<p>
<label>
Count of '+' key presses:
<input value="@count" @onkeydown="KeyHandler" @onkeydown:preventDefault />
</label>
</p>
@code {
private int count = 0;
private void KeyHandler(KeyboardEventArgs e)
{
if (e.Key == "+")
{
count++;
}
}
}
EventHandlerExample6.razor
:
@page "/event-handler-example-6"
<p>
<input value="@count" @onkeydown="KeyHandler" @onkeydown:preventDefault />
</p>
@code {
private int count = 0;
private void KeyHandler(KeyboardEventArgs e)
{
if (e.Key == "+")
{
count++;
}
}
}
EventHandlerExample6.razor
:
@page "/event-handler-example-6"
<p>
<input value="@count" @onkeydown="KeyHandler" @onkeydown:preventDefault />
</p>
@code {
private int count = 0;
private void KeyHandler(KeyboardEventArgs e)
{
if (e.Key == "+")
{
count++;
}
}
}
EventHandlerExample6.razor
:
@page "/event-handler-example-6"
<p>
<input value="@count" @onkeydown="KeyHandler" @onkeydown:preventDefault />
</p>
@code {
private int count = 0;
private void KeyHandler(KeyboardEventArgs e)
{
if (e.Key == "+")
{
count++;
}
}
}
EventHandlerExample6.razor
:
@page "/event-handler-example-6"
<p>
<input value="@count" @onkeydown="KeyHandler" @onkeydown:preventDefault />
</p>
@code {
private int count = 0;
private void KeyHandler(KeyboardEventArgs e)
{
if (e.Key == "+")
{
count++;
}
}
}
Указание атрибута @on{DOM EVENT}:preventDefault
без значения эквивалентно @on{DOM EVENT}:preventDefault="true"
.
Выражение также является допустимым значением атрибута. В следующем примере shouldPreventDefault
является полем bool
, для которого задано значение true
или false
:
<input @onkeydown:preventDefault="shouldPreventDefault" />
...
@code {
private bool shouldPreventDefault = true;
}
Остановка распространения событий
Используйте атрибут директивы @on{DOM EVENT}:stopPropagation
, чтобы остановить распространение событий в области Blazor.
{DOM EVENT}
— это заполнитель для события DOM.
Результат атрибута директивы stopPropagation
ограничен областью Blazor и не распространяется на модель DOM HTML. События должны распространиться в корневой элемент DOM HTML, прежде чем Blazor сможет предпринимать действия с ними. Для механизма предотвращения распространения событий модели DOM HTML используйте следующий подход:
- Получите путь события, вызвав метод
Event.composedPath()
. - Фильтруйте события на основе составных целевых объектов (
EventTarget
).
В приведенном ниже примере установка флажка предотвращает распространение событий щелчка мышью из второго дочернего элемента <div>
в родительский элемент <div>
. Так как распространенные события щелчка мышью обычно вызывают метод OnSelectParentDiv
, выбор второго дочернего элемента <div>
приводит к отображению родительского сообщения <div>
в случае, если флажок не установлен.
EventHandler7.razor
:
@page "/event-handler-7"
<PageTitle>Event Handler 7</PageTitle>
<h1>Event Handler Example 7</h1>
<div>
<b>stopPropagation</b>: @stopPropagation
</div>
<div>
<button @onclick="StopPropagation">
Stop Propagation (stopPropagation = true)
</button>
<button @onclick="EnablePropagation">
Enable Propagation (stopPropagation = false)
</button>
</div>
<div class="m-1 p-1 border border-primary" @onclick="OnSelectParentDiv">
<h3>Parent div</h3>
<div class="m-1 p-1 border" @onclick="OnSelectChildDiv">
Child div that never stops propagation to the parent div when
selected.
</div>
<div class="m-1 p-1 border" @onclick="OnSelectChildDiv"
@onclick:stopPropagation="stopPropagation">
Child div that stops propagation when selected if
<b>stopPropagation</b> is <b>true</b>.
</div>
</div>
<p>
@message
</p>
@code {
private bool stopPropagation = false;
private string? message;
private void StopPropagation() => stopPropagation = true;
private void EnablePropagation() => stopPropagation = false;
private void OnSelectParentDiv() =>
message = $"The parent div was selected. {DateTime.Now}";
private void OnSelectChildDiv() =>
message = $"The child div was selected. {DateTime.Now}";
}
EventHandler7.razor
:
@page "/event-handler-7"
<PageTitle>Event Handler 7</PageTitle>
<h1>Event Handler Example 7</h1>
<div>
<b>stopPropagation</b>: @stopPropagation
</div>
<div>
<button @onclick="StopPropagation">
Stop Propagation (stopPropagation = true)
</button>
<button @onclick="EnablePropagation">
Enable Propagation (stopPropagation = false)
</button>
</div>
<div class="m-1 p-1 border border-primary" @onclick="OnSelectParentDiv">
<h3>Parent div</h3>
<div class="m-1 p-1 border" @onclick="OnSelectChildDiv">
Child div that never stops propagation to the parent div when
selected.
</div>
<div class="m-1 p-1 border" @onclick="OnSelectChildDiv"
@onclick:stopPropagation="stopPropagation">
Child div that stops propagation when selected if
<b>stopPropagation</b> is <b>true</b>.
</div>
</div>
<p>
@message
</p>
@code {
private bool stopPropagation = false;
private string? message;
private void StopPropagation() => stopPropagation = true;
private void EnablePropagation() => stopPropagation = false;
private void OnSelectParentDiv() =>
message = $"The parent div was selected. {DateTime.Now}";
private void OnSelectChildDiv() =>
message = $"The child div was selected. {DateTime.Now}";
}
EventHandlerExample7.razor
:
@page "/event-handler-example-7"
<div>
<b>stopPropagation</b>: @stopPropagation
</div>
<div>
<button @onclick="StopPropagation">
Stop Propagation (stopPropagation = true)
</button>
<button @onclick="EnablePropagation">
Enable Propagation (stopPropagation = false)
</button>
</div>
<div class="m-1 p-1 border border-primary" @onclick="OnSelectParentDiv">
<h3>Parent div</h3>
<div class="m-1 p-1 border" @onclick="OnSelectChildDiv">
Child div that never stops propagation to the parent div when
selected.
</div>
<div class="m-1 p-1 border" @onclick="OnSelectChildDiv"
@onclick:stopPropagation="stopPropagation">
Child div that stops propagation when selected if
<b>stopPropagation</b> is <b>true</b>.
</div>
</div>
<p>
@message
</p>
@code {
private bool stopPropagation = false;
private string? message;
private void StopPropagation() => stopPropagation = true;
private void EnablePropagation() => stopPropagation = false;
private void OnSelectParentDiv() =>
message = $"The parent div was selected. {DateTime.Now}";
private void OnSelectChildDiv() =>
message = $"The child div was selected. {DateTime.Now}";
}
EventHandlerExample7.razor
:
@page "/event-handler-example-7"
<div>
<b>stopPropagation</b>: @stopPropagation
</div>
<div>
<button @onclick="StopPropagation">
Stop Propagation (stopPropagation = true)
</button>
<button @onclick="EnablePropagation">
Enable Propagation (stopPropagation = false)
</button>
</div>
<div class="m-1 p-1 border border-primary" @onclick="OnSelectParentDiv">
<h3>Parent div</h3>
<div class="m-1 p-1 border" @onclick="OnSelectChildDiv">
Child div that never stops propagation to the parent div when
selected.
</div>
<div class="m-1 p-1 border" @onclick="OnSelectChildDiv"
@onclick:stopPropagation="stopPropagation">
Child div that stops propagation when selected if
<b>stopPropagation</b> is <b>true</b>.
</div>
</div>
<p>
@message
</p>
@code {
private bool stopPropagation = false;
private string? message;
private void StopPropagation() => stopPropagation = true;
private void EnablePropagation() => stopPropagation = false;
private void OnSelectParentDiv() =>
message = $"The parent div was selected. {DateTime.Now}";
private void OnSelectChildDiv() =>
message = $"The child div was selected. {DateTime.Now}";
}
EventHandlerExample7.razor
:
@page "/event-handler-example-7"
<div>
<b>stopPropagation</b>: @stopPropagation
</div>
<div>
<button @onclick="StopPropagation">
Stop Propagation (stopPropagation = true)
</button>
<button @onclick="EnablePropagation">
Enable Propagation (stopPropagation = false)
</button>
</div>
<div class="m-1 p-1 border border-primary" @onclick="OnSelectParentDiv">
<h3>Parent div</h3>
<div class="m-1 p-1 border" @onclick="OnSelectChildDiv">
Child div that never stops propagation to the parent div when
selected.
</div>
<div class="m-1 p-1 border" @onclick="OnSelectChildDiv"
@onclick:stopPropagation="stopPropagation">
Child div that stops propagation when selected if
<b>stopPropagation</b> is <b>true</b>.
</div>
</div>
<p>
@message
</p>
@code {
private bool stopPropagation = false;
private string message;
private void StopPropagation() => stopPropagation = true;
private void EnablePropagation() => stopPropagation = false;
private void OnSelectParentDiv() =>
message = $"The parent div was selected. {DateTime.Now}";
private void OnSelectChildDiv() =>
message = $"The child div was selected. {DateTime.Now}";
}
EventHandlerExample7.razor
:
@page "/event-handler-example-7"
<div>
<b>stopPropagation</b>: @stopPropagation
</div>
<div>
<button @onclick="StopPropagation">
Stop Propagation (stopPropagation = true)
</button>
<button @onclick="EnablePropagation">
Enable Propagation (stopPropagation = false)
</button>
</div>
<div class="m-1 p-1 border border-primary" @onclick="OnSelectParentDiv">
<h3>Parent div</h3>
<div class="m-1 p-1 border" @onclick="OnSelectChildDiv">
Child div that never stops propagation to the parent div when
selected.
</div>
<div class="m-1 p-1 border" @onclick="OnSelectChildDiv"
@onclick:stopPropagation="stopPropagation">
Child div that stops propagation when selected if
<b>stopPropagation</b> is <b>true</b>.
</div>
</div>
<p>
@message
</p>
@code {
private bool stopPropagation = false;
private string message;
private void StopPropagation() => stopPropagation = true;
private void EnablePropagation() => stopPropagation = false;
private void OnSelectParentDiv() =>
message = $"The parent div was selected. {DateTime.Now}";
private void OnSelectChildDiv() =>
message = $"The child div was selected. {DateTime.Now}";
}
Установка фокуса на элемент
Вызовите FocusAsync для ссылки на элемент, чтобы установить фокус на элемент в коде. В следующем примере нажмите кнопку, чтобы установить фокус на элемент <input>
.
EventHandler8.razor
:
@page "/event-handler-8"
<PageTitle>Event Handler 8</PageTitle>
<h1>Event Handler Example 8</h1>
<p>Select the button to give the <code><input></code> focus.</p>
<p>
<label>
Input:
<input @ref="exampleInput" />
</label>
</p>
<button @onclick="ChangeFocus">
Focus the Input Element
</button>
@code {
private ElementReference exampleInput;
private async Task ChangeFocus()
{
await exampleInput.FocusAsync();
}
}
EventHandler8.razor
:
@page "/event-handler-8"
<PageTitle>Event Handler 8</PageTitle>
<h1>Event Handler Example 8</h1>
<p>Select the button to give the <code><input></code> focus.</p>
<p>
<label>
Input:
<input @ref="exampleInput" />
</label>
</p>
<button @onclick="ChangeFocus">
Focus the Input Element
</button>
@code {
private ElementReference exampleInput;
private async Task ChangeFocus()
{
await exampleInput.FocusAsync();
}
}
EventHandlerExample8.razor
:
@page "/event-handler-example-8"
<p>
<input @ref="exampleInput" />
</p>
<button @onclick="ChangeFocus">
Focus the Input Element
</button>
@code {
private ElementReference exampleInput;
private async Task ChangeFocus()
{
await exampleInput.FocusAsync();
}
}
EventHandlerExample8.razor
:
@page "/event-handler-example-8"
<p>
<input @ref="exampleInput" />
</p>
<button @onclick="ChangeFocus">
Focus the Input Element
</button>
@code {
private ElementReference exampleInput;
private async Task ChangeFocus()
{
await exampleInput.FocusAsync();
}
}
ASP.NET Core