ASP.NET Core Blazor 이벤트 처리

참고 항목

이 문서의 최신 버전은 아닙니다. 현재 릴리스는 이 문서의 .NET 8 버전을 참조 하세요.

Important

이 정보는 상업적으로 출시되기 전에 실질적으로 수정될 수 있는 시험판 제품과 관련이 있습니다. Microsoft는 여기에 제공된 정보에 대해 어떠한 명시적, 또는 묵시적인 보증을 하지 않습니다.

현재 릴리스는 이 문서의 .NET 8 버전을 참조 하세요.

이 문서에서는 이벤트 인수 형식, 이벤트 콜백, 기본 브라우저 이벤트 관리를 비롯한 Blazor의 이벤트 처리 기능을 설명합니다.

대리자 이벤트 처리기

구문을 사용하여 구성 요소 태그 @on{DOM EVENT}="{DELEGATE}"Razor 에 Razor 대리자 이벤트 처리기를 지정합니다.

  • {DOM EVENT} 자리 표시자는 DOM 이벤트(예: click)입니다.
  • {DELEGATE} 자리 표시자는 C# 대리자 이벤트 처리기입니다.

이벤트 처리인 경우:

  • Task를 반환하는 비동기 대리자 이벤트 처리기가 지원됩니다.
  • 대리자 이벤트 처리기는 UI 렌더링을 자동으로 트리거하므로 StateHasChanged를 수동으로 호출할 필요가 없습니다.
  • 예외가 기록됩니다.

코드는 다음과 같습니다.

  • UI에서 단추를 선택할 때 UpdateHeading 메서드를 호출합니다.
  • UI에서 확인란을 변경할 때 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 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}";
    }
}

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:

  • 단추를 선택할 때 비동기적으로 호출됩니다.
  • 제목을 업데이트할 때까지 2초간 기다립니다.

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})";
    }
}

기본 제공 이벤트 인수

이벤트 인수 형식을 지원하는 이벤트인 경우 이벤트 유형이 메서드에서 사용될 때만 이벤트 메서드 정의에 이벤트 매개 변수를 지정해야 합니다. 다음 예제에서는 ReportPointerLocation 메서드에서 MouseEventArgs를 사용하여 사용자가 UI에서 단추를 선택할 때 마우스 좌표를 보고하는 메시지 텍스트를 설정합니다.

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 DataTransferDataTransferItem은 끌어온 항목 데이터를 포함합니다.

JS interopHTML 끌어서 놓기 API와 함께 사용하여 Blazor 앱에서 끌어서 놓기를 구현합니다.
Error ErrorEventArgs
이벤트 EventArgs EventHandlers에는 이벤트 이름과 이벤트 인수 형식 간의 매핑을 구성하는 특성이 있습니다.
포커스 FocusEventArgs relatedTarget 지원을 포함하지 않습니다.
입력 ChangeEventArgs
Keyboard KeyboardEventArgs
마우스 MouseEventArgs
Mouse pointer PointerEventArgs
마우스 휠 WheelEventArgs
진행률 ProgressEventArgs
터치 TouchEventArgs TouchPoint는 터치 인식 디바이스에서 단일 접촉 지점을 나타냅니다.

자세한 내용은 다음 리소스를 참조하세요.

사용자 지정 이벤트 인수

Blazor는 사용자 지정 이벤트를 사용하여 .NET 이벤트 처리기로 임의 데이터를 전달할 수 있도록 하는 사용자 지정 이벤트 인수를 지원합니다.

일반 구성

사용자 지정 이벤트 인수를 사용하는 사용자 지정 이벤트는 일반적으로 다음 단계에 따라 사용하도록 설정합니다.

JavaScript에서 소스 이벤트의 사용자 지정 이벤트 인수 개체를 빌드하기 위한 함수를 정의합니다.

function eventArgsCreator(event) { 
  return {
    customProperty1: 'any value for property 1',
    customProperty2: event.srcElement.id
  };
}

event 매개 변수는 DOM 이벤트(MDN 설명서)입니다.

JavaScript 이니셜라이저에서 이전 처리기에 사용자 지정 이벤트를 등록합니다. 적절한 브라우저 이벤트 이름을 browserEventName제공합니다. 이 섹션에 표시된 예제는 UI의 단추 선택용입니다 click .

wwwroot/{PACKAGE ID/ASSEMBLY NAME}.lib.module.js{PACKAGE ID/ASSEMBLY NAME} 자리 표시자는 앱의 패키지 ID 또는 어셈블리 이름입니다.

웹앱의 Blazor 경우:

export function afterWebStarted(blazor) {
  blazor.registerCustomEventType('customevent', {
    browserEventName: 'click',
    createEventArgs: eventArgsCreator
  });
}

또는 Blazor WebAssembly 앱의 Blazor Server 경우:

export function afterStarted(blazor) {
  blazor.registerCustomEventType('customevent', {
    browserEventName: 'click',
    createEventArgs: eventArgsCreator
  });
}

참고 항목

registerCustomEventType은 이벤트당 한 번만 스크립트에서 호출됩니다.

호출registerCustomEventType의 경우 시작 이벤트에서 제공하는 Blazor 매개 변수(소문자b)를 사용합니다blazor. 개체(대문자B)를 사용할 Blazor 때 등록이 유효하지만 매개 변수를 사용하는 것이 좋습니다.

이벤트 인수에 대한 클래스를 정의합니다.

namespace BlazorSample.CustomEvents;

public class CustomEventArgs : EventArgs
{
    public string? CustomProperty1 {get; set;}
    public string? CustomProperty2 {get; set;}
}

사용자 지정 이벤트에 대한 특성 주석을 추가하여 [EventHandler] 이벤트 인수와 사용자 지정 이벤트를 연결합니다.

  • 컴파일러가 클래스를 찾으 [EventHandler] 려면 C# 클래스 파일().cs에 배치하여 일반 최상위 클래스로 만들어야 합니다.
  • 클래스 public를 표시합니다.
  • 클래스에는 멤버가 필요하지 않습니다.
  • 컴파일러에서 찾을 Razor 수 있도록 클래스를 "EventHandlers"라고 해야 합니다.
  • 클래스를 앱과 관련된 네임스페이스 아래에 배치합니다.
  • 네임스페이스를 이벤트가 사용되는 구성 요소(.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;
    }
}

IntelliSense에서 @oncustomevent 특성을 인식하지 못하는 경우 구성 요소 또는 _Imports.razor 파일에 EventHandler 클래스가 포함된 네임스페이스에 대한 @using 문이 포함되어 있는지 확인합니다.

DOM에서 사용자 지정 이벤트가 발생할 때마다 JavaScript에서 전달된 데이터를 사용하여 이벤트 처리기가 호출됩니다.

사용자 지정 이벤트를 발생시키려는 경우 해당 값을 true로 설정하여 bubbles를 사용하도록 설정해야 합니다. 그렇지 않으면 이벤트가 C# 사용자 지정 [EventHandler] 특성 클래스로 처리하기 위한 처리기에 도달하지 Blazor 않습니다. 자세한 내용은 MDN 웹 문서: 이벤트 버블링을 참조하세요.

사용자 지정 클립보드 붙여넣기 이벤트 예제

다음 예제에서는 붙여넣기 시간과 사용자가 붙여넣은 텍스트를 포함하는 사용자 지정 클립보드 붙여넣기 이벤트를 수신합니다.

이벤트의 사용자 지정 이름(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 코드를 추가합니다. 다음 예제에서는 텍스트 붙여넣기만 처리하지만, 임의의 JavaScript API를 사용하여 이미지와 같은 다른 형식의 데이터 붙여넣기도 처리할 수 있습니다.

wwwroot/{PACKAGE ID/ASSEMBLY NAME}.lib.module.js:

웹앱의 Blazor 경우:

export function afterWebStarted(blazor) {
  blazor.registerCustomEventType('custompaste', {
    browserEventName: 'paste',
    createEventArgs: event => {
      return {
        eventTimestamp: new Date(),
        pastedData: event.clipboardData.getData('text')
      };
    }
  });
}

또는 Blazor WebAssembly 앱의 Blazor Server 경우:

export function afterStarted(blazor) {
  blazor.registerCustomEventType('custompaste', {
    browserEventName: 'paste',
    createEventArgs: event => {
      return {
        eventTimestamp: new Date(),
        pastedData: event.clipboardData.getData('text')
      };
    }
  });
}

앞의 예제 {PACKAGE ID/ASSEMBLY NAME} 에서 파일 이름의 자리 표시자는 앱의 패키지 ID 또는 어셈블리 이름을 나타냅니다.

참고 항목

호출registerCustomEventType의 경우 시작 이벤트에서 제공하는 Blazor 매개 변수(소문자b)를 사용합니다blazor. 개체(대문자B)를 사용할 Blazor 때 등록이 유효하지만 매개 변수를 사용하는 것이 좋습니다.

위의 코드는 네이티브 paste 이벤트가 발생할 때 브라우저에 다음을 지시합니다.

  • custompaste 이벤트를 발생시킵니다.
  • 다음과 같은 사용자 지정 논리를 사용하여 이벤트 인수 데이터를 제공합니다.

.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";
}

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을 호출하고 다음 데이터를 전달합니다.

  • e의 이벤트 인수(MouseEventArgs).
  • 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}";
    }
}

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 성능 모범 사례를 참조하세요.

for 루프 예제의 i와 같이 람다 식에서 직접 루프 변수를 사용하지 않습니다. 직접 사용하는 경우 모든 람다 식에서 동일한 변수가 사용되어 모든 람다에서 동일한 값이 사용됩니다. 로컬 변수에서 변수의 값을 캡처합니다. 앞의 예에서:

  • 루프 변수 ibuttonNumber에 할당됩니다.
  • buttonNumber는 람다 식에서 사용됩니다.

또는 위의 문제가 발생하지 않는 Enumerable.Range를 가진 foreach 루프를 사용합니다.

@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 처리기가 샘플의 ParentComponent에서 EventCallback 대리자를 수신하도록 설정하는 방법을 보여 줍니다. EventCallback은 주변 디바이스의 onclick 이벤트에 적합한 MouseEventArgs 형식입니다.

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; }
}

Parent 구성 요소는 자식의 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})";
    }
}

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 구성 요소를 다시 렌더링하도록 자동으로 호출됩니다. 자세한 내용은 ASP.NET Core Razor 구성 요소 렌더링을 참조하세요.

이벤트 처리 및 바인딩 구성 요소 매개 변수에 EventCallbackEventCallback<TValue>을 사용합니다.

EventCallback보다 강력한 형식의 EventCallback<TValue>를 사용하는 것이 좋습니다. EventCallback<TValue> 에서는 부적절한 형식을 사용할 때 향상된 오류 피드백을 제공하여 구성 요소의 사용자를 올바른 구현으로 안내합니다. 다른 UI 이벤트 처리기와 마찬가지로 이벤트 매개 변수 지정은 선택 사항입니다. 콜백에 전달되는 값이 없는 경우 EventCallback을 사용합니다.

EventCallbackEventCallback<TValue>는 비동기 대리자를 허용합니다. EventCallback은 약한 형식이며 InvokeAsync(Object)에서 모든 형식 인수를 전달할 수 있습니다. EventCallback<TValue>은 강력한 형식이며 InvokeAsync(T)에서 TValue에 할당할 수 있는 T 인수를 전달해야 합니다.

InvokeAsync를 사용하여 EventCallback 또는 EventCallback<TValue>를 호출하고 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 값이 할당되고 2초 지연으로 렌더링됩니다.

기본 작업 방지

@on{DOM EVENT}:preventDefault 지시문 특성을 사용하여 자리 표시자가 DOM 이벤트인 {DOM EVENT} 이벤트에 대한 기본 동작을 방지합니다.

입력 디바이스에서 키를 선택하고 요소 포커스가 텍스트 상자에 놓이면 일반적으로 브라우저의 텍스트 상자에 키 문자가 표시됩니다. 다음 예제에서는 @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++;
        }
    }
}

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"와 동일합니다.

또한 식은 특성의 허용되는 값입니다. 다음 예제에서 shouldPreventDefaulttrue 또는 false로 설정되는 bool 필드입니다.

<input @onkeydown:preventDefault="shouldPreventDefault" />

...

@code {
    private bool shouldPreventDefault = true;
}

이벤트 전파 중지

@on{DOM EVENT}:stopPropagation 지시문 특성을 사용하여 Blazor 범위 내에서 이벤트 전파를 중지합니다. {DOM EVENT}는 DOM 이벤트의 자리 표시자입니다.

stopPropagation 지시문 특성의 효과는 Blazor 범위로 제한되며 HTML DOM으로 확장되지 않습니다. Blazor가 작동하려면 먼저 이벤트가 HTML DOM 루트에 전파되어야 합니다. HTML DOM 이벤트 전파를 방지하는 메커니즘의 경우 다음 방법을 고려합니다.

다음 예제에서 확인란을 선택하면 두 번째 자식 <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}";
}

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();
    }
}

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();
    }
}