obsługa zdarzeń ASP.NET Core Blazor

Uwaga

Nie jest to najnowsza wersja tego artykułu. Aby zapoznać się z bieżącą wersją, zapoznaj się z wersją tego artykułu platformy .NET 8.

Ważne

Te informacje odnoszą się do produktu w wersji wstępnej, który może zostać znacząco zmodyfikowany, zanim zostanie wydany komercyjnie. Firma Microsoft nie udziela żadnych gwarancji, jawnych lub domniemanych, w odniesieniu do informacji podanych w tym miejscu.

Aby zapoznać się z bieżącą wersją, zapoznaj się z wersją tego artykułu platformy .NET 8.

W tym artykule wyjaśniono Blazorfunkcje obsługi zdarzeń, w tym typy argumentów zdarzeń, wywołania zwrotne zdarzeń i zarządzanie domyślnymi zdarzeniami przeglądarki.

Delegowanie procedur obsługi zdarzeń

Określ procedury obsługi zdarzeń delegata w Razor znacznikach składników za pomocą @on{DOM EVENT}="{DELEGATE}"Razor składni:

  • Symbol {DOM EVENT} zastępczy to zdarzenie DOM (na przykład click).
  • Symbol {DELEGATE} zastępczy to procedura obsługi zdarzeń delegata języka C#.

Obsługa zdarzeń:

  • Asynchroniczne procedury obsługi zdarzeń delegatów, które zwracają element Task , są obsługiwane.
  • Deleguj programy obsługi zdarzeń automatycznie wyzwalają renderowanie interfejsu użytkownika, więc nie ma potrzeby ręcznego wywoływania elementu StateHasChanged.
  • Wyjątki są rejestrowane.

Następujący kod powoduje:

  • Wywołuje metodę UpdateHeading po wybraniu przycisku w interfejsie użytkownika.
  • Wywołuje metodę CheckChanged po zmianie pola wyboru w interfejsie użytkownika.

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

W poniższym przykładzie: UpdateHeading

  • Jest wywoływany asynchronicznie po wybraniu przycisku.
  • Czeka dwa sekundy przed zaktualizowaniem nagłówka.

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

Wbudowane argumenty zdarzeń

W przypadku zdarzeń obsługujących typ argumentu zdarzenia określenie parametru zdarzenia w definicji metody zdarzenia jest konieczne tylko wtedy, gdy typ zdarzenia jest używany w metodzie . W poniższym przykładzie MouseEventArgs użyto ReportPointerLocation metody , aby ustawić tekst komunikatu, który raportuje współrzędne myszy, gdy użytkownik wybierze przycisk w interfejsie użytkownika.

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

Obsługiwane EventArgs są przedstawione w poniższej tabeli.

Zdarzenie Klasa Uwagi DOM
Schowek ClipboardEventArgs
Przeciągnij DragEventArgs DataTransfer i DataTransferItem przytrzymaj przeciągnięte dane elementu.

Zaimplementuj przeciąganie i upuszczanie aplikacji za pomocą JS interfejsuAPI przeciągania i upuszczania Blazor HTML.
Błąd ErrorEventArgs
Zdarzenie EventArgs EventHandlers przechowuje atrybuty do konfigurowania mapowań między nazwami zdarzeń i typami argumentów zdarzeń.
Ukierunkowanie FocusEventArgs Nie obejmuje obsługi programu relatedTarget.
Dane wejściowe ChangeEventArgs
Klawiatura KeyboardEventArgs
mysz (Keyboard, Video, Mouse) MouseEventArgs
Mouse pointer PointerEventArgs
Koło myszy WheelEventArgs
Postęp ProgressEventArgs
Dotyk TouchEventArgs TouchPoint reprezentuje pojedynczy punkt kontaktu na urządzeniu z uwzględnieniem dotyku.

Aby uzyskać więcej informacji, zobacz następujące zasoby:

Niestandardowe argumenty zdarzeń

Blazor Obsługuje niestandardowe argumenty zdarzeń, które umożliwiają przekazywanie dowolnych danych do programów obsługi zdarzeń platformy .NET z niestandardowymi zdarzeniami.

Konfiguracja ogólna

Zdarzenia niestandardowe z niestandardowymi argumentami zdarzeń są zwykle włączone, wykonując następujące kroki.

W języku JavaScript zdefiniuj funkcję służącą do kompilowania niestandardowego obiektu argumentu zdarzenia z zdarzenia źródłowego:

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

Parametr event jest zdarzeniem DOM (dokumentacja MDN).

Zarejestruj zdarzenie niestandardowe przy użyciu poprzedniego programu obsługi w inicjatorze języka JavaScript. Podaj odpowiednią nazwę zdarzenia przeglądarki na browserEventName, która dla przykładu pokazanego w tej sekcji dotyczy click wyboru przycisku w interfejsie użytkownika.

wwwroot/{PACKAGE ID/ASSEMBLY NAME}.lib.module.js{PACKAGE ID/ASSEMBLY NAME}(symbol zastępczy to identyfikator pakietu lub nazwa zestawu aplikacji):

W przypadku Blazor aplikacji internetowej:

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

W przypadku aplikacji Blazor Server lub Blazor WebAssembly :

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

Uwaga

Wywołanie metody jest registerCustomEventType wykonywane w skrycie tylko raz na zdarzenie.

W przypadku wywołania metody registerCustomEventTypeużyj parametru blazor (małe litery b) dostarczonego Blazor przez zdarzenie początkowe. Chociaż rejestracja jest prawidłowa w przypadku używania Blazor obiektu (wielkie litery B), preferowaną metodą jest użycie parametru .

Zdefiniuj klasę argumentów zdarzeń:

namespace BlazorSample.CustomEvents;

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

Podłącz zdarzenie niestandardowe z argumentami zdarzeń, dodając adnotację [EventHandler] atrybutu dla zdarzenia niestandardowego:

  • Aby kompilator znalazł klasę [EventHandler] , musi zostać umieszczony w pliku klasy C# (.cs), co czyni ją normalną klasą najwyższego poziomu.
  • Oznacz klasę public.
  • Klasa nie wymaga elementów członkowskich.
  • Klasa musi być nazywana "EventHandlers" w celu znalezienia Razor przez kompilator.
  • Umieść klasę w przestrzeni nazw specyficznej dla aplikacji.
  • Zaimportuj Razor przestrzeń nazw do składnika (.razor), w którym jest używane zdarzenie.
using Microsoft.AspNetCore.Components;

namespace BlazorSample.CustomEvents;

[EventHandler("oncustomevent", typeof(CustomEventArgs),
    enableStopPropagation: true, enablePreventDefault: true)]
public static class EventHandlers
{
}

Zarejestruj procedurę obsługi zdarzeń na co najmniej jednym elemecie HTML. Uzyskaj dostęp do danych przekazanych z języka JavaScript w metodzie procedury obsługi delegatów:

@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 Jeśli atrybut nie jest rozpoznawany przez funkcję IntelliSense, upewnij się, że składnik lub _Imports.razor plik zawiera instrukcję dla przestrzeni nazw zawierającej klasę @usingEventHandler.

Za każdym razem, gdy zdarzenie niestandardowe jest uruchamiane w modelu DOM, program obsługi zdarzeń jest wywoływany z danymi przekazywanymi z języka JavaScript.

Jeśli próbujesz uruchomić zdarzenie niestandardowe, należy je włączyć, bubbles ustawiając jego wartość na true. W przeciwnym razie zdarzenie nie dociera do Blazor procedury obsługi przetwarzania do niestandardowej klasy atrybutów języka C#[EventHandler]. Aby uzyskać więcej informacji, zobacz MDN Web Docs: Event bubbling.

Przykład zdarzenia wklejania niestandardowego schowka

Poniższy przykład odbiera niestandardowe zdarzenie wklejania schowka, które obejmuje czas wklejania i wklejonego tekstu użytkownika.

Zadeklaruj niestandardową nazwę (oncustompaste) dla zdarzenia i klasę .NET (CustomPasteEventArgs), aby przechowywać argumenty zdarzeń dla tego zdarzenia:

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

Dodaj kod JavaScript, aby dostarczyć dane dla EventArgs podklasy z poprzednim programem obsługi w inicjatorze języka JavaScript. Poniższy przykład obsługuje tylko wklejanie tekstu, ale można użyć dowolnych interfejsów API języka JavaScript do obsługi wklejania innych typów danych, takich jak obrazy.

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

W przypadku Blazor aplikacji internetowej:

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

W przypadku aplikacji Blazor Server lub Blazor WebAssembly :

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

W poprzednim przykładzie {PACKAGE ID/ASSEMBLY NAME} symbol zastępczy nazwy pliku reprezentuje identyfikator pakietu lub nazwę zestawu aplikacji.

Uwaga

W przypadku wywołania metody registerCustomEventTypeużyj parametru blazor (małe litery b) dostarczonego Blazor przez zdarzenie początkowe. Chociaż rejestracja jest prawidłowa w przypadku używania Blazor obiektu (wielkie litery B), preferowaną metodą jest użycie parametru .

Powyższy kod informuje przeglądarkę, że gdy wystąpi zdarzenie natywne paste :

  • custompaste Zgłoś zdarzenie.
  • Podaj dane argumentów zdarzeń przy użyciu podanej logiki niestandardowej:

Konwencje nazw zdarzeń różnią się między platformą .NET i językiem JavaScript:

  • Na platformie .NET nazwy zdarzeń mają prefiks "on".
  • W języku JavaScript nazwy zdarzeń nie mają prefiksu.

W składniku dołącz niestandardową procedurę Razor obsługi do elementu.

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

Wyrażenia lambda

Wyrażenia lambda są obsługiwane jako program obsługi zdarzeń delegata.

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

Często wygodne jest zamknięcie dodatkowych wartości przy użyciu parametrów metody języka C#, takich jak iteracja nad zestawem elementów. W poniższym przykładzie są tworzone trzy przyciski, z których każde wywołuje UpdateHeading i przekazuje następujące dane:

  • Argument zdarzenia (MouseEventArgs) w elem.e
  • Numer przycisku w elem 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}";
    }
}

Utworzenie dużej liczby delegatów zdarzeń w pętli może spowodować niską wydajność renderowania. Aby uzyskać więcej informacji, zobacz ASP.NET Core performance best practices (Najlepsze rozwiązania dotyczące wydajności ASP.NET CoreBlazor).

Unikaj używania zmiennej pętli bezpośrednio w wyrażeniu lambda, takim jak i w poprzednim przykładzie for pętli. W przeciwnym razie ta sama zmienna jest używana przez wszystkie wyrażenia lambda, co powoduje użycie tej samej wartości we wszystkich wyrażeniach lambda. Przechwyć wartość zmiennej w zmiennej lokalnej. W powyższym przykładzie:

  • Zmienna pętli jest przypisywana do buttonNumberzmiennej i .
  • buttonNumber jest używany w wyrażeniu lambda.

Alternatywnie należy użyć foreach pętli z elementem Enumerable.Range, która nie ma problemu z poprzednim:

@foreach (var buttonNumber in Enumerable.Range(1,3))
{
    <p>
        <button @onclick="@(e => UpdateHeading(e, buttonNumber))">
            Button #@buttonNumber
        </button>
    </p>
}

EventCallback

Typowy scenariusz ze składnikami zagnieżdżonym polega na wykonaniu metody w składniku nadrzędnym, gdy wystąpi zdarzenie składnika podrzędnego. Zdarzenie onclick występujące w składniku podrzędnym jest typowym przypadkiem użycia. Aby uwidocznić zdarzenia między składnikami, użyj elementu EventCallback. Składnik nadrzędny może przypisać metodę wywołania zwrotnego do składnika podrzędnego EventCallback.

Poniższy Child składnik pokazuje, jak skonfigurowana jest procedura obsługi przycisku onclick w celu odbierania EventCallback delegata z przykładu ParentComponent. Typ EventCallback jest typu MouseEventArgs, który jest odpowiedni dla onclick zdarzenia z urządzenia peryferyjnego.

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

Składnik Parent ustawia element podrzędny EventCallback<TValue> (OnClickCallback) na jego ShowMessage metodę.

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

Po wybraniu przycisku w elemecie ChildComponent:

  • Parent Wywoływana ShowMessage jest metoda składnika. message element jest aktualizowany i wyświetlany w składniku Parent .
  • Wywołanie metody StateHasChanged nie jest wymagane w metodzie wywołania zwrotnego (ShowMessage). StateHasChanged element jest wywoływany automatycznie, aby rerender Parent składnika, podobnie jak zdarzenia podrzędne wyzwalały rerendering składnika w programach obsługi zdarzeń wykonywanych w ramach elementu podrzędnego. Aby uzyskać więcej informacji, zobacz Renderowanie składników platformy ASP.NET Core Razor.

Użyj parametrów EventCallback składnika obsługi zdarzeń i EventCallback<TValue> powiązania.

Preferuj silnie typizowane EventCallback<TValue> niż EventCallback. EventCallback<TValue> udostępnia ulepszone opinie o błędach, gdy jest używany niewłaściwy typ, kierując użytkowników składnika do poprawnej implementacji. Podobnie jak w przypadku innych procedur obsługi zdarzeń interfejsu użytkownika, określenie parametru zdarzenia jest opcjonalne. Użyj EventCallback polecenia , jeśli nie ma wartości przekazanej do wywołania zwrotnego.

EventCallback i EventCallback<TValue> zezwalaj na asynchroniczne delegaty. EventCallbackjest słabo wpisywany i umożliwia przekazanie dowolnego argumentu typu w .InvokeAsync(Object) EventCallback<TValue> jest silnie typizowane i wymaga przekazania argumentu T w InvokeAsync(T) pliku , który można przypisać do TValueelementu .

Wywołaj element EventCallback lub za pomocą InvokeAsync polecenia i poczekaj na polecenie TaskEventCallback<TValue> :

await OnClickCallback.InvokeAsync({ARGUMENT});

W poprzednim przykładzie {ARGUMENT} symbol zastępczy jest opcjonalnym argumentem.

W poniższym przykładzie nadrzędny-podrzędny przedstawiono technikę.

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

Drugie wystąpienie Child2 składnika demonstruje wywołanie zwrotne asynchroniczne, a nowa message2 wartość jest przypisywana i renderowana z opóźnieniem dwóch sekund.

Zapobieganie akcjam domyślnym

Użyj atrybutu @on{DOM EVENT}:preventDefault dyrektywy, aby zapobiec domyślnej akcji zdarzenia, gdzie {DOM EVENT} symbol zastępczy jest zdarzeniem DOM.

Po wybraniu klucza na urządzeniu wejściowym, a fokus elementu znajduje się w polu tekstowym, przeglądarka zwykle wyświetla znak klucza w polu tekstowym. W poniższym przykładzie domyślne zachowanie jest blokowane przez określenie atrybutu @onkeydown:preventDefault dyrektywy. Gdy fokus znajduje się na elemecie<input>, licznik zwiększa się z sekwencją klawiszy Shift++. Znak + nie jest przypisany do <input> wartości elementu. Aby uzyskać więcej informacji na keydowntemat programu , zobacz MDN Web Docs: Document: keydown zdarzenie.

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

Określenie atrybutu @on{DOM EVENT}:preventDefault bez wartości jest równoważne .@on{DOM EVENT}:preventDefault="true"

Wyrażenie jest również dozwoloną wartością atrybutu. W poniższym przykładzie shouldPreventDefault jest polem ustawionym bool na true wartość lub false:

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

...

@code {
    private bool shouldPreventDefault = true;
}

Zatrzymaj propagację zdarzeń

Użyj atrybutu @on{DOM EVENT}:stopPropagation dyrektywy, aby zatrzymać propagację zdarzeń w Blazor zakresie. {DOM EVENT} jest symbolem zastępczym zdarzenia DOM.

stopPropagation Efekt atrybutu dyrektywy jest ograniczony do Blazor zakresu i nie rozciąga się na dom HTML. Zdarzenia muszą być propagowane do katalogu głównego DOM HTML, zanim Blazor będą mogły działać na nich. Aby zapobiec propagacji zdarzeń DOM HTML, należy wziąć pod uwagę następujące podejście:

W poniższym przykładzie zaznaczenie pola wyboru uniemożliwia propagację zdarzeń z drugiego elementu podrzędnego <div> do elementu nadrzędnego <div>. Ponieważ propagowane zdarzenia kliknięcia zwykle uruchamiają metodę OnSelectParentDiv , wybranie drugiego elementu podrzędnego <div> powoduje wyświetlenie komunikatu nadrzędnego <div> , chyba że zaznaczono pole wyboru.

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

Fokus elementu

Wywołaj FocusAsync odwołanie do elementu, aby skoncentrować element w kodzie. W poniższym przykładzie wybierz przycisk, aby skoncentrować element <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();
    }
}