Dołączanie kodu C# do zdarzeń DOM za pomocą procedur obsługi zdarzeń platformy Blazor
Większość elementów HTML uwidacznia zdarzenia, które są wyzwalane w przypadku wystąpienia istotnego zdarzenia, na przykład po zakończeniu ładowania strony, użytkownik kliknął przycisk lub zmieniono zawartość elementu HTML. Aplikacja może obsługiwać zdarzenie na kilka sposobów:
- Aplikacja może zignorować zdarzenie.
- Aplikacja może uruchomić program obsługi zdarzeń napisany w języku JavaScript w celu przetworzenia zdarzenia.
- Aplikacja może uruchomić program obsługi zdarzeń platformy Blazor napisany w języku C#, aby przetworzyć zdarzenie.
W tej lekcji przyjrzysz się szczegółowo trzeciej opcji; jak utworzyć program obsługi zdarzeń platformy Blazor w języku C#, aby przetworzyć zdarzenie.
Obsługa zdarzenia za pomocą platformy Blazor i języka C#
Każdy element w adiustacji HTML aplikacji Blazor obsługuje wiele zdarzeń. Większość z tych zdarzeń odpowiada zdarzeń DOM dostępnych w zwykłych aplikacjach internetowych, ale można również tworzyć zdarzenia zdefiniowane przez użytkownika, które są wyzwalane przez pisanie kodu. Aby przechwycić zdarzenie za pomocą platformy Blazor, należy napisać metodę języka C#, która obsługuje zdarzenie, a następnie powiązać zdarzenie z metodą za pomocą dyrektywy Blazor. W przypadku zdarzenia DOM dyrektywa Blazor ma taką samą nazwę jak równoważne zdarzenie HTML, takie jak @onkeydown
lub @onfocus
. Na przykład przykładowa aplikacja wygenerowana przy użyciu aplikacji serwera Blazor zawiera następujący kod na stronie Counter.razor . Na tej stronie jest wyświetlany przycisk. Gdy użytkownik wybierze IncrementCount
przycisk, zdarzenie wyzwala metodę, @onclick
która zwiększa licznik wskazujący liczbę kliknięć przycisku. Wartość zmiennej licznika jest wyświetlana przez <element p> na stronie:
@page "/counter"
<h1>Counter</h1>
<p>Current count: @currentCount</p>
<button class="btn btn-primary" @onclick="IncrementCount">Click me</button>
@code {
private int currentCount = 0;
private void IncrementCount()
{
currentCount++;
}
}
Wiele metod obsługi zdarzeń ma parametr, który udostępnia dodatkowe informacje kontekstowe. Ten parametr jest znany jako EventArgs
parametr. Na przykład zdarzenie przekazuje informacje o tym, @onclick
który przycisk kliknął użytkownik, lub czy naciśnął przycisk, taki jak Ctrl lub Alt w tym samym czasie, co kliknięcie przycisku, w parametrze MouseEventArgs
. Nie musisz podawać tego parametru podczas wywoływania metody. środowisko uruchomieniowe platformy Blazor dodaje je automatycznie. Ten parametr można wykonać w procedurze obsługi zdarzeń. Poniższy kod zwiększa licznik pokazany w poprzednim przykładzie o pięć, jeśli użytkownik naciska Ctrl w tym samym czasie, co kliknięcie przycisku:
@page "/counter"
<h1>Counter</h1>
<p>Current count: @currentCount</p>
<button class="btn btn-primary" @onclick="IncrementCount">Click me</button>
@code {
private int currentCount = 0;
private void IncrementCount(MouseEventArgs e)
{
if (e.CtrlKey) // Ctrl key pressed as well
{
currentCount += 5;
}
else
{
currentCount++;
}
}
}
Inne zdarzenia zapewniają różne EventArgs
parametry. Na przykład @onkeypress
zdarzenie przekazuje KeyboardEventArgs
parametr wskazujący, który został naciśnięty przez użytkownika. W przypadku dowolnego zdarzenia DOM, jeśli nie potrzebujesz tych informacji, możesz pominąć EventArgs
parametr z metody obsługi zdarzeń.
Omówienie obsługi zdarzeń w języku JavaScript i obsługi zdarzeń za pomocą platformy Blazor
Tradycyjna aplikacja internetowa używa języka JavaScript do przechwytywania i przetwarzania zdarzeń. Funkcja jest tworzona jako część elementu skryptu> HTML<, a następnie rozmieszczana w celu wywołania tej funkcji po wystąpieniu zdarzenia. W porównaniu z poprzednim przykładem platformy Blazor poniższy kod przedstawia fragment ze strony HTML, która zwiększa wartość i wyświetla wynik za każdym razem, gdy użytkownik wybierze przycisk Kliknij mnie . Kod korzysta z biblioteki jQuery w celu uzyskania dostępu do modelu DOM.
<p id="currentCount">Current count: 0</p>
<button class="btn btn-primary" onclick="incrementCount()">Click me</button>
<!-- Omitted for brevity -->
<script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
<script>
var currentCount = 0;
function incrementCount() {
currentCount++;
$('#currentCount').html('Current count:' + currentCount);
}
</script>
Oprócz różnic składniowych w dwóch wersjach programu obsługi zdarzeń należy zwrócić uwagę na następujące różnice funkcjonalne:
- Język JavaScript nie prefiksuje nazwy zdarzenia z znakiem
@
; nie jest to dyrektywa Blazor. - W kodzie platformy Blazor należy określić nazwę metody obsługi zdarzeń podczas dołączania jej do zdarzenia. W języku JavaScript piszesz instrukcję, która wywołuje metodę obsługi zdarzeń; należy określić nawiasy okrągłe i wszystkie wymagane parametry.
- Co najważniejsze, program obsługi zdarzeń języka JavaScript jest uruchamiany w przeglądarce na kliencie. Jeśli tworzysz aplikację serwera Blazor, program obsługi zdarzeń platformy Blazor jest uruchamiany na serwerze i aktualizuje przeglądarkę tylko za pomocą wszelkich zmian wprowadzonych w interfejsie użytkownika po zakończeniu obsługi zdarzeń. Ponadto mechanizm Blazor umożliwia programowi obsługi zdarzeń dostęp do danych statycznych udostępnianych między sesjami; model JavaScript nie. Jednak obsługa niektórych często występujących zdarzeń, takich jak
@onmousemove
może spowodować, że interfejs użytkownika stanie się powolny, ponieważ wymagają one rundy sieciowej na serwerze. Wolisz obsługiwać zdarzenia, takie jak te w przeglądarce, przy użyciu języka JavaScript.
Ważne
Możesz manipulować modelem DOM przy użyciu kodu JavaScript z programu obsługi zdarzeń, a także przy użyciu kodu C# Blazor. Jednak platforma Blazor utrzymuje własną kopię modelu DOM, która jest używana do odświeżania interfejsu użytkownika w razie potrzeby. Jeśli używasz kodu JavaScript i Blazor, aby zmienić te same elementy w modelu DOM, ryzyko uszkodzenia modelu DOM i ewentualnie naruszenie prywatności i bezpieczeństwa danych w aplikacji internetowej.
Asynchroniczna obsługa zdarzeń
Domyślnie programy obsługi zdarzeń platformy Blazor są synchroniczne. Jeśli program obsługi zdarzeń wykonuje potencjalnie długotrwałą operację, taką jak wywoływanie usługi internetowej, wątek, na którym działa program obsługi zdarzeń, zostanie zablokowany do momentu zakończenia operacji. Może to prowadzić do niskiej reakcji w interfejsie użytkownika. Aby to zrobić, można wyznaczyć metodę obsługi zdarzeń jako asynchroniczną. Użyj słowa kluczowego C# async
. Metoda musi zwrócić Task
obiekt. Następnie można użyć await
operatora wewnątrz metody obsługi zdarzeń, aby zainicjować wszystkie długotrwałe zadania w osobnym wątku i zwolnić bieżący wątek do innych zadań. Po zakończeniu długotrwałego zadania program obsługi zdarzeń zostanie wznowione. Przykładowa procedura obsługi zdarzeń poniżej uruchamia metodę czasochłonną asynchronicznie:
<button @onclick="DoWork">Run time-consuming operation</button>
@code {
private async Task DoWork()
{
// Call a method that takes a long time to run and free the current thread
var data = await timeConsumingOperation();
// Omitted for brevity
}
}
Uwaga
Aby uzyskać szczegółowe informacje na temat tworzenia metod asynchronicznych w języku C#, przeczytaj Asynchroniczne scenariusze programowania.
Ustawianie fokusu na element DOM za pomocą zdarzenia
Na stronie HTML użytkownik może karty między elementami, a fokus naturalnie podróżuje w kolejności, w jakiej elementy HTML pojawiają się na stronie. Czasami może być konieczne zastąpienie tej sekwencji i wymusić na użytkowniku wizytę określonego elementu.
Najprostszym sposobem wykonania tego zadania jest użycie FocusAsync
metody . Jest to metoda ElementReference
wystąpienia obiektu. Element ElementReference
powinien odwoływać się do elementu, do którego chcesz ustawić fokus. Należy wyznaczyć odwołanie do elementu z atrybutem @ref
i utworzyć obiekt języka C# o tej samej nazwie w kodzie.
W poniższym przykładzie @onclick
program obsługi zdarzeń dla <elementu przycisku> ustawia fokus na elemecie wejściowym<>. Procedura @onfocus
obsługi zdarzeń elementu wejściowego> <wyświetla komunikat "Odebrano fokus", gdy element pobiera fokus. Element <wejściowy> jest przywołyyny za pośrednictwem zmiennej InputField
w kodzie:
<button class="btn btn-primary" @onclick="ChangeFocus">Click me to change focus</button>
<input @ref=InputField @onfocus="HandleFocus" value="@data"/>
@code {
private ElementReference InputField;
private string data;
private async Task ChangeFocus()
{
await InputField.FocusAsync();
}
private async Task HandleFocus()
{
data = "Received focus";
}
Na poniższej ilustracji przedstawiono wynik po wybraniu przycisku przez użytkownika:
Uwaga
Aplikacja powinna kierować fokus tylko do określonej kontrolki z określonego powodu, na przykład poprosić użytkownika o zmodyfikowanie danych wejściowych po błędzie. Nie używaj koncentracji uwagi, aby wymusić na użytkowniku nawigowanie po elementach na stronie w stałej kolejności; Może to być bardzo frustrujące dla użytkownika, który może chcieć ponownie przejrzeć elementy, aby zmienić swoje dane wejściowe.
Pisanie wbudowanych procedur obsługi zdarzeń
Język C# obsługuje wyrażenia lambda. Wyrażenie lambda umożliwia utworzenie funkcji anonimowej. Wyrażenie lambda jest przydatne, jeśli masz prostą procedurę obsługi zdarzeń, której nie trzeba używać ponownie w innym miejscu na stronie lub składniku. W przykładzie liczby kliknięć początkowych pokazanych na początku tej lekcji możesz usunąć IncrementCount
metodę i zamiast tego zastąpić wywołanie metody wyrażeniem lambda wykonującym to samo zadanie:
@page "/counter"
<h1>Counter</h1>
<p>Current count: @currentCount</p>
<button class="btn btn-primary" @onclick="() => currentCount++">Click me</button>
@code {
private int currentCount = 0;
}
Uwaga
Aby uzyskać szczegółowe informacje na temat sposobu działania wyrażeń lambda, przeczytaj wyrażenia lambda i funkcje anonimowe.
Takie podejście jest również przydatne, jeśli chcesz podać inne argumenty dla metody obsługi zdarzeń. W poniższym przykładzie metoda HandleClick
przyjmuje MouseEventArgs
parametr w taki sam sposób, jak zwykły program obsługi zdarzeń kliknięcia, ale akceptuje również parametr ciągu. Metoda przetwarza zdarzenie kliknięcia tak jak poprzednio, ale także wyświetla komunikat w użytkowniku naciśnięty Ctrl . Wyrażenie lambda wywołuje metodę HandleCLick
, przekazując MouseEventArgs
parametr (mouseEvent
) i ciąg.
@page "/counter"
@inject IJSRuntime JS
<h1>Counter</h1>
<p id="currentCount">Current count: @currentCount</p>
<button class="btn btn-primary" @onclick='mouseEvent => HandleClick(mouseEvent, "Hello")'>Click me</button>
@code {
private int currentCount = 0;
private async Task HandleClick(MouseEventArgs e, string msg)
{
if (e.CtrlKey) // Ctrl key pressed as well
{
await JS.InvokeVoidAsync("alert", msg);
currentCount += 5;
}
else
{
currentCount++;
}
}
}
Uwaga
W tym przykładzie użyto funkcji Języka JavaScript alert
do wyświetlenia komunikatu, ponieważ w blazorze nie ma równoważnej funkcji. Aby wywołać kod JavaScript z kodu Blazor, należy użyć międzyoperacji języka JavaScript. Szczegóły tej techniki dotyczą oddzielnego modułu.
Zastąpij domyślne akcje DOM dla zdarzeń
Kilka zdarzeń DOM ma domyślne akcje, które są uruchamiane po wystąpieniu zdarzenia, niezależnie od tego, czy istnieje program obsługi zdarzeń dostępny dla tego zdarzenia. Na przykład @onkeypress
zdarzenie elementu wejściowego <> zawsze wyświetla znak odpowiadający, który użytkownik naciśnął i obsługuje naciśnięcie. W następnym przykładzie @onkeypress
zdarzenie jest używane do konwertowania danych wejściowych użytkownika na wielkie litery. Ponadto, jeśli użytkownik wpisze @
znak, program obsługi zdarzeń wyświetla alert:
<input value=@data @onkeypress="ProcessKeyPress"/>
@code {
private string data;
private async Task ProcessKeyPress(KeyboardEventArgs e)
{
if (e.Key == "@")
{
await JS.InvokeVoidAsync("alert", "You pressed @");
}
else
{
data += e.Key.ToUpper();
}
}
}
Jeśli uruchomisz ten kod i naciśniesz @
, zostanie wyświetlony alert, ale @
do danych wejściowych zostanie również dodany znak. Dodanie @
znaku jest domyślną akcją zdarzenia.
Jeśli chcesz pominąć ten znak przed pojawieniem się w polu wejściowym, możesz zastąpić domyślną akcję atrybutem preventDefault
zdarzenia w następujący sposób:
<input value=@data @onkeypress="ProcessKeyPress" @onkeypress:preventDefault />
Zdarzenie będzie nadal uruchamiane, ale zostaną wykonane tylko akcje zdefiniowane przez program obsługi zdarzeń.
Niektóre zdarzenia w elemecie podrzędnym w modelu DOM mogą wyzwalać zdarzenia w elementach nadrzędnych. W poniższym przykładzie <element div> zawiera procedurę obsługi zdarzeń @onclick
. Przycisk <> wewnątrz <elementu div> ma własną @onclick
procedurę obsługi zdarzeń. <Ponadto element div> zawiera <element wejściowy>:
<div @onclick="HandleDivClick">
<button class="btn btn-primary" @onclick="IncrementCount">Click me</button>
<input value=@data @onkeypress="ProcessKeyPress" @onkeypress:preventDefault />
</div>
@code {
private async Task HandleDivClick()
{
await JS.InvokeVoidAsync("alert", "Div click");
}
private async Task ProcessKeyPress(KeyboardEventArgs e)
{
// Omitted for brevity
}
private int currentCount = 0;
private void IncrementCount(MouseEventArgs e)
{
// Omitted for brevity
}
}
Gdy aplikacja zostanie uruchomiona, jeśli użytkownik kliknie dowolny element (lub puste miejsce) w obszarze zajmowanym <przez element div> , metoda HandleDivClick
zostanie uruchomiona i wyświetli komunikat. Jeśli użytkownik wybierze Click me
przycisk, IncrementCount
metoda zostanie uruchomiona, a następnie , @onclick
a następnie HandleDivClick
zdarzenie propaguje drzewo DOM. <Jeśli element div> był częścią innego elementu, który również obsłużył @onclick
zdarzenie, program obsługi zdarzeń również zostanie uruchomiony i tak dalej, do katalogu głównego drzewa DOM. Można ograniczyć tę liczbę zdarzeń w górę z stopPropagation
atrybutem zdarzenia, jak pokazano poniżej:
<div @onclick="HandleDivClick">
<button class="btn btn-primary" @onclick="IncrementCount" @onclick:stopPropagation>Click me</button>
<!-- Omitted for brevity -->
</div>
Używanie klasy EventCallback do obsługi zdarzeń między składnikami
Strona platformy Blazor może zawierać co najmniej jeden składnik platformy Blazor, a składniki mogą być zagnieżdżone w relacji nadrzędny-podrzędny. Zdarzenie w składniku podrzędnym może wyzwolić metodę obsługi zdarzeń w składniku nadrzędnym przy użyciu elementu EventCallback
. Wywołanie zwrotne odwołuje się do metody w składniku nadrzędnym. Składnik podrzędny może uruchomić metodę, wywołując wywołanie zwrotne. Ten mechanizm jest podobny do użycia elementu , delegate
aby odwołać się do metody w aplikacji języka C#.
Wywołanie zwrotne może przyjmować jeden parametr. EventCallback
jest typem ogólnym. Parametr typu określa typ argumentu przekazanego do wywołania zwrotnego.
Rozważmy na przykład następujący scenariusz. Chcesz utworzyć składnik o nazwie TextDisplay
, który umożliwia użytkownikowi wprowadzanie ciągu wejściowego i przekształcanie tego ciągu w jakiś sposób. Możesz też przekonwertować go na wielkie litery, małe litery, wielkość liter mieszanych, znaki filtru lub wykonać inny typ przekształcenia. Jednak podczas pisania kodu dla TextDisplay
składnika nie wiadomo, jaki będzie proces przekształcania, i zamiast tego chcesz odroczyć tę operację na inny składnik. Poniższy kod przedstawia TextDisplay
składnik. Udostępnia on ciąg wejściowy w postaci elementu wejściowego<>, który umożliwia użytkownikowi wprowadzanie wartości tekstowej.
@* TextDisplay component *@
@using WebApplication.Data;
<p>Enter text:</p>
<input @onkeypress="HandleKeyPress" value="@data" />
@code {
[Parameter]
public EventCallback<KeyTransformation> OnKeyPressCallback { get; set; }
private string data;
private async Task HandleKeyPress(KeyboardEventArgs e)
{
KeyTransformation t = new KeyTransformation() { Key = e.Key };
await OnKeyPressCallback.InvokeAsync(t);
data += t.TransformedKey;
}
}
Składnik TextDisplay
używa EventCallback
obiektu o nazwie OnKeyPressCallback
. Kod w metodzie HandleKeypress
wywołuje wywołanie zwrotne. Procedura @onkeypress
obsługi zdarzeń jest uruchamiana przy każdym naciśnięciu i wywołaniu HandleKeypress
metody . Metoda HandleKeypress
tworzy KeyTransformation
obiekt przy użyciu naciśnięty przez użytkownika i przekazuje ten obiekt jako parametr do wywołania zwrotnego. Typ KeyTransformation
jest prostą klasą z dwoma polami:
namespace WebApplication.Data
{
public class KeyTransformation
{
public string Key { get; set; }
public string TransformedKey { get; set; }
}
}
Pole key
zawiera wartość wprowadzoną przez użytkownika, a TransformedKey
pole będzie przechowywać przekształconą wartość klucza po jego przetworzeniu.
W tym przykładzie EventCallback
obiekt jest parametrem składnika, a jego wartość jest dostarczana podczas tworzenia składnika. Ta akcja jest wykonywana przez inny składnik o nazwie TextTransformer
:
@page "/texttransformer"
@using WebApplication.Data;
<h1>Text Transformer - Parent</h1>
<TextDisplay OnKeypressCallback="@TransformText" />
@code {
private void TransformText(KeyTransformation k)
{
k.TransformedKey = k.Key.ToUpper();
}
}
Składnik TextTransformer
jest stroną platformy Blazor, która tworzy wystąpienie TextDisplay
składnika. OnKeypressCallback
Wypełnia parametr odwołaniem do TransformText
metody w sekcji kodu strony. Metoda TransformText
przyjmuje KeyTransformation
obiekt podany jako argument i wypełnia TransformedKey
właściwość wartością znajdującą się we Key
właściwości przekonwertowanej na wielkie litery. Na poniższym diagramie przedstawiono przepływ sterowania, gdy użytkownik wprowadza wartość do <pola wejściowego> w składniku TextDisplay
wyświetlanym przez TextTransformer
stronę:
Piękno tego podejścia polega na tym, że można użyć TextDisplay
składnika z dowolną stroną, która zapewnia wywołanie zwrotne dla parametru OnKeypressCallback
. Istnieje całkowite rozdzielenie między wyświetlaczem a przetwarzaniem. Możesz przełączyć metodę TransformText
dla dowolnego innego wywołania zwrotnego zgodnego z podpisem EventCallback
parametru w składniku TextDisplay
.
Wywołanie zwrotne można połączyć bezpośrednio z procedurą obsługi zdarzeń bez użycia metody pośredniej, jeśli wywołanie zwrotne jest wpisywane przy użyciu odpowiedniego EventArgs
parametru. Na przykład składnik podrzędny może odwoływać się do wywołania zwrotnego, który może obsługiwać zdarzenia myszy, takie jak @onclick
następujące:
<button @onclick="OnClickCallback">
Click me!
</button>
@code {
[Parameter]
public EventCallback<MouseEventArgs> OnClickCallback { get; set; }
}
W tym przypadku EventCallback
parametr przyjmuje parametr typu, więc można go określić jako procedurę MouseEventArgs
obsługi dla @onclick
zdarzenia.