Trudny / egzaminacyjny · lekcja 29

Komponenty Blazor — parametry, zdarzenia własne i cykl życia

Prawdziwa aplikacja nie mieści się w jednym komponencie — dzieli się na mniejsze, wielokrotnego użytku klocki (np. "karta produktu", "przycisk oceny gwiazdkami"), które przekazują sobie dane i informują się nawzajen o zdarzeniach. To dokładnie ta sama potrzeba...

Zacznij tutaj

Po co się tego uczymy?

Prawdziwa aplikacja nie mieści się w jednym komponencie — dzieli się na mniejsze, wielokrotnego użytku klocki (np. "karta produktu", "przycisk oceny gwiazdkami"), które przekazują sobie dane i informują się nawzajen o zdarzeniach. To dokładnie ta sama potrzeba, którą w dziale MAUI rozwiązywał DataTemplate w CollectionView — tu poznasz analogiczny mechanizm w Blazor: komponenty potomne, parametry wejściowe i zdarzenia wychodzące.

Wprowadzenie

Teoria

Komponent potomny i parametry. Każdy plik .razor to jednocześnie DEFINICJA komponentu, którego można użyć wewnątrz INNEGO komponentu jak zwykłego znacznika HTML: <KartaProduktu Nazwa="Klawiatura" Cena="89.99" />. Żeby komponent KartaProduktu mógł PRZYJĄĆ takie dane, jego właściwości muszą być oznaczone atrybutem [Parameter] — to bezpośredni odpowiednik przekazywania danych do strony przez konstruktor w lekcji o nawigacji w dziale MAUI, tylko realizowany przez atrybuty znaczników HTML zamiast kodu C#.

Zdarzenia własne — komunikacja OD komponentu potomnego DO rodzica. Parametry przekazują dane W DÓŁ (rodzic → dziecko), ale co, gdy komponent potomny musi POINFORMOWAĆ rodzica o czymś (np. "użytkownik kliknął ten konkretny produkt")? Do tego służy właściwość typu EventCallback<T> oznaczona [Parameter] — rodzic przekazuje METODĘ do wywołania (<KartaProduktu OnKliknieto="ObslugaKlikniecia" />), a komponent potomny wywołuje ją w odpowiednim momencie przez await OnKliknieto.InvokeAsync(wartosc). To bezpośredni odpowiednik zdarzeń Clicked/Click podpinanych w XAML z działów WPF/MAUI, tylko teraz to TY definiujesz WŁASNE, niestandardowe zdarzenie na swoim komponencie.

Cykl życia komponentu — metody wywoływane automatycznie:

MetodaKiedy się wykonuje
OnInitialized() / OnInitializedAsync()RAZ, przy pierwszym utworzeniu komponentu — dobre miejsce na pobranie początkowych danych (np. z bazy)
OnParametersSet()za KAŻDYM razem, gdy zmienią się parametry przekazane przez rodzica
OnAfterRender(bool pierwszyRaz)PO wyrenderowaniu komponentu w przeglądarce — jedyne bezpieczne miejsce na wywołania JavaScript (JS interop) albo operacje wymagające gotowego DOM
Dispose() (interfejs IDisposable)gdy komponent jest usuwany z ekranu — dobre miejsce na sprzątanie (np. zatrzymanie timera z poprzedniej lekcji)

To bezpośredni odpowiednik konstruktora MainPage() i zdarzenia OnAppearing z lekcji o nawigacji w dziale MAUI — tylko w Blazor cykl życia ma WIĘCEJ, bardziej precyzyjnie rozdzielonych etapów.

Dyrektywa @ChildContent. Komponenty mogą też przyjmować DOWOLNĄ treść HTML/Razor MIĘDZY swoimi znacznikami otwierającym/zamykającym (jak <div>treść</div>) — właściwość [Parameter] public RenderFragment? ChildContent { get; set; } przechwytuje tę treść, a @ChildContent w widoku komponentu wskazuje, gdzie ją wstawić — przydatne przy budowaniu np. reużywalnej "karty" czy "okna dialogowego" o zmiennej zawartości.

Zobacz zależności

Schemat

Komponent RODZICA (np. ListaProduktow.razor)
        │
        │  <KartaProduktu Nazwa="Klawiatura" Cena="89.99"
        │                 OnKliknieto="ObsluzKlikniecie" />
        ▼
Komponent POTOMNY (KartaProduktu.razor)
   [Parameter] public string Nazwa { get; set; }        ← DANE W DÓŁ
   [Parameter] public double Cena { get; set; }
   [Parameter] public EventCallback<string> OnKliknieto { get; set; }
        │
        │  użytkownik klika kartę
        ▼
   await OnKliknieto.InvokeAsync(Nazwa)                 ← ZDARZENIE W GÓRĘ
        │
        ▼
Komponent RODZICA: ObsluzKlikniecie(string nazwa) { ... }

Cykl życia komponentu (kolejność wywołań):
OnInitialized() → OnParametersSet() → renderowanie → OnAfterRender(true)
        │
        │  (zmiana parametru od rodzica)
        ▼
OnParametersSet() → ponowne renderowanie → OnAfterRender(false)

Połącz z praktyką

Przykład z życia

Lista produktów w sklepie internetowym renderowana z wielu powtarzających się komponentów "Karta produktu" (nazwa, cena, przycisk "Dodaj do koszyka") — każda karta jest osobnym, samodzielnym komponentem, ale gdy użytkownik kliknie "Dodaj do koszyka" na KONKRETNEJ karcie, komponent rodzica (lista) musi się o tym dowiedzieć, żeby zaktualizować licznik koszyka widoczny gdzie indziej na stronie — dokładnie ten scenariusz pokazuje przykład w tej lekcji.