Model komponentów Blazor
Twórz komponenty Razor, poznaj cykl życia komponentu oraz używaj parametrów i wartości kaskadowych.
Model komponentów Blazor to bezpłatna lekcja C# Academy na CoddyKit. To lekcja 1 z 4. Możesz przeczytać całą lekcję poniżej za darmo — a potem ćwiczyć ją interaktywnie w przeglądarce z wbudowanym edytorem kodu i tutorem AI dostępnym 24/7. To część ścieżki edukacyjnej C# Academy, a Twój postęp synchronizuje się między webem a aplikacją CoddyKit. Kurs C# Academy zawiera 4 lekcji w sumie.
Czym jest Blazor?
Blazor umożliwia tworzenie interaktywnych interfejsów internetowych przy użyciu C# zamiast JavaScript. Komponenty definiuje się w plikach .razor, które łączą znaczniki HTML z logiką C#. Blazor działa na serwerze (Blazor Server) lub w przeglądarce za pośrednictwem WebAssembly (Blazor WASM).
Pierwszy komponent
Komponent Razor to plik .razor zawierający znaczniki HTML oraz blok @code z kodem C#. Nazwa komponentu staje się nazwą znacznika HTML.
@* Greeting.razor *@
<h2>Hello, @Name!</h2>
<p>You have @Count messages.</p>
@code {
[Parameter] public string Name { get; set; } = "World";
private int Count = 5;
}Cykl życia komponentu
Komponenty Blazor mają cykl życia z punktami zaczepienia, które można przesłaniać. Najczęściej używane są OnInitializedAsync (ładowanie danych) oraz OnParametersSetAsync (reagowanie na zmiany parametrów).
@code {
private List<Product> Products = new();
protected override async Task OnInitializedAsync()
{
// Called once on first render
Products = await Http.GetFromJsonAsync<List<Product>>("/api/products")
?? new();
}
protected override async Task OnParametersSetAsync()
{
// Called whenever parameters change
await LoadDataAsync();
}
}Parametry: przekazywanie danych do komponentów
Należy oznaczyć właściwości atrybutem [Parameter], aby przyjmowały dane z komponentów nadrzędnych. Parametry są ustawiane przed renderowaniem, a ich zmiana może wywołać ponowne renderowanie.
@* ProductCard.razor *@
<div class="card">
<h4>@Product.Name</h4>
<p>Price: @Product.Price.ToString("C")</p>
<button @onclick="AddToCart">Add to Cart</button>
</div>
@code {
[Parameter, EditorRequired]
public Product Product { get; set; } = default!;
[Parameter]
public EventCallback<Product> OnAddToCart { get; set; }
private async Task AddToCart() =>
await OnAddToCart.InvokeAsync(Product);
}Parametry kaskadowe
Parametry kaskadowe przepływają w dół drzewa komponentów bez konieczności jawnego przekazywania ich przez każdy poziom pośredni — idealnie nadają się do motywów, informacji o użytkowniku lub współdzielonego stanu.
@* App.razor — wraps the whole app *@
<CascadingValue Value="CurrentUser">
<Router AppAssembly="@typeof(App).Assembly">
<Found Context="routeData">
<RouteView RouteData="routeData" DefaultLayout="@typeof(MainLayout)" />
</Found>
</Router>
</CascadingValue>
@* Anywhere in the tree: *@
@code {
[CascadingParameter]
public UserInfo CurrentUser { get; set; } = default!;
}Renderowanie list i warunków
Do renderowania dynamicznej zawartości należy używać dyrektyw Razor @if, @foreach i @for. Elementom listy należy zawsze nadawać @key, aby wydajnie wykrywać różnice.
@if (Products.Count == 0)
{
<p>No products found.</p>
}
else
{
<ul>
@foreach (var product in Products)
{
<li @key="product.Id">
<ProductCard Product="product" OnAddToCart="HandleAdd" />
</li>
}
</ul>
}RenderFragment i ChildContent
Należy używać RenderFragment do przekazywania znaczników jako parametru — podobnie jak slotów w Vue lub children w React. Konwencjonalna nazwa parametru to ChildContent.
@* Panel.razor *@
<div class="panel">
<div class="panel-header">@Title</div>
<div class="panel-body">@ChildContent</div>
</div>
@code {
[Parameter] public string Title { get; set; } = "";
[Parameter] public RenderFragment? ChildContent { get; set; }
}
@* Usage: *@
<Panel Title="Order Details">
<p>Order #42 — Shipped</p>
</Panel>Referencje do komponentów za pomocą @ref
Za pomocą @ref można przechwycić referencję do komponentu podrzędnego, aby wywoływać jego publiczne metody lub odczytywać jego właściwości z komponentu nadrzędnego.
@* Parent.razor *@
<ConfirmDialog @ref="_dialog" OnConfirm="DeleteOrder" />
<button @onclick="() => _dialog!.Show()">Delete Order</button>
@code {
private ConfirmDialog? _dialog;
private async Task DeleteOrder()
{
await OrderService.DeleteAsync(CurrentOrderId);
// Refresh UI...
}
}StateHasChanged i ręczne ponowne renderowanie
Blazor automatycznie renderuje komponent ponownie po wykonaniu procedur obsługi zdarzeń. W przypadku asynchronicznych zmian stanu poza procedurami obsługi zdarzeń (np. wywołanych przez czasomierz działający w tle) należy ręcznie wywołać StateHasChanged().
@implements IDisposable
<p>Time: @CurrentTime</p>
@code {
private string CurrentTime = "";
private Timer? _timer;
protected override void OnInitialized()
{
_timer = new Timer(_ =>
{
CurrentTime = DateTime.Now.ToString("HH:mm:ss");
InvokeAsync(StateHasChanged); // thread-safe re-render
}, null, 0, 1000);
}
public void Dispose() => _timer?.Dispose();
}ShouldRender na potrzeby wydajności
Należy przesłonić ShouldRender(), aby pomijać niepotrzebne ponowne renderowanie. Gdy dane wyjściowe komponentu się nie zmienią, należy zwrócić false, ograniczając koszt wykrywania różnic.
@code {
private string _lastRenderedStatus = "";
[Parameter] public string Status { get; set; } = "";
protected override bool ShouldRender()
{
// Only re-render if Status actually changed
if (Status == _lastRenderedStatus) return false;
_lastRenderedStatus = Status;
return true;
}
}Praktyczny przykład: komponent listy produktów
Kompletny komponent listy produktów, który ładuje dane podczas inicjalizacji, obsługuje stan ładowania i przekazuje zdarzenia do komponentu nadrzędnego.
@inject HttpClient Http
@if (_loading)
{
<p>Loading products...</p>
}
else
{
@foreach (var p in _products)
{
<ProductCard Product="p" OnAddToCart="AddToCart" />
}
}
@code {
private List<Product> _products = new();
private bool _loading = true;
[Parameter] public EventCallback<Product> OnCartUpdated { get; set; }
protected override async Task OnInitializedAsync()
{
_products = await Http.GetFromJsonAsync<List<Product>>("/api/products")
?? new();
_loading = false;
}
private async Task AddToCart(Product p) => await OnCartUpdated.InvokeAsync(p);
}Szybkie sprawdzenie
W której metodzie cyklu życia najlepiej ładować dane z API podczas inicjalizacji komponentu Blazor?
Podsumowanie: model komponentów Blazor
Najważniejsze informacje:
- Pliki .razor łączą znaczniki HTML z kodem C# w bloku @code
- [Parameter] przyjmuje dane od komponentu nadrzędnego, a EventCallback przekazuje zdarzenia w górę
- CascadingParameter przekazuje dane w dół bez prop-drillingu
- RenderFragment/ChildContent umożliwia tworzenie komponowalnych komponentów opartych na slotach
- OnInitializedAsync służy do początkowego ładowania danych, a StateHasChanged do ręcznego ponownego renderowania
- ShouldRender() pomija niepotrzebne wykrywanie różnic, zwiększając wydajność
Często zadawane pytania
Czy lekcja „Model komponentów Blazor” jest bezpłatna?
Tak — pełny tekst „Model komponentów Blazor” jest dostępny za darmo tutaj w sieci. Aby ćwiczyć ją interaktywnie (wbudowany edytor kodu i tutor AI dostępny 24/7) i odblokować resztę kursu C# Academy, przejdź na CoddyKit PRO. Kurs C# Academy zawiera 4 lekcji w sumie.
Co nauczysz się w „Model komponentów Blazor”?
Twórz komponenty Razor, poznaj cykl życia komponentu oraz używaj parametrów i wartości kaskadowych. Ćwiczysz C# Academy z praktycznym kodem, który uruchamiasz bezpośrednio w przeglądarce, a tutor AI dostępny 24/7 odpowiada na Twoje pytania podczas pracy nad lekcją.
Czy potrzebuję doświadczenia, aby zacząć C# Academy?
Nie wymagamy żadnego doświadczenia. C# Academy w CoddyKit jest strukturyzowany dla początkujących i zaawansowanych użytkowników, więc możesz zacząć tutaj lub od początku i uczyć się w swoim tempie. To lekcja 1 z 4.
Ile czasu zajmuje lekcja „Model komponentów Blazor”?
Większość lekcji CoddyKit trwa około 5–10 minut. Każda lekcja to mały, interaktywny krok, dzięki czemu robisz systematyczne postępy i zawsze wracasz dokładnie do tego samego miejsca — na webie i w aplikacji.
Czy mogę pisać i uruchamiać kod w tej lekcji C# Academy?
Tak. Każda lekcja C# Academy zawiera wbudowany edytor kodu, więc piszesz i uruchamiasz prawdziwy kod bezpośrednio w przeglądarce i od razu otrzymujesz sprzężenie zwrotne od AI — bez konfiguracji na komputerze.
Wszystkie lekcje w tym kursie
- Model komponentów Blazor
- Wiązanie danych i obsługa zdarzeń
- Komunikacja komponentów i DI
- Zarządzanie stanem w Blazor