Blazor vanaf nul: Hoofdstuk 3 — Componenten die schalen
Welkom bij Hoofdstuk 3 van Blazor vanaf nul. Als je Hoofdstuk 2 hebt gemist, lees dat eerst zodat je basisproject klaarstaat.
In Hoofdstuk 2 kregen we de app draaiend. In dit hoofdstuk maken we hem onderhoudbaar.
Blazor-projecten worden snel rommelig als elke pagina een gigantisch .razor-bestand wordt. Componenten voorkomen dat: meer consistentie, meer hergebruik en duidelijke grenzen tussen UI-delen.
Wat een Blazor-component echt is
Een component is een .razor-bestand dat:
- Markup rendert
- Lokale state bevat
- Input accepteert via parameters
- Events naar parent-componenten stuurt
- Child content rendert
Tijdens runtime behandelt Blazor elke component als een kleine state machine. Bij state-wijzigingen rendert Blazor opnieuw en past het een DOM-diff toe.
Doel: duidelijke input en voorspelbaar gedrag.
Stap 1: Begin met een gerichte component
Maak Components/Common/SectionHeader.razor:
<header class="section-header">
<h2>@Title</h2>
@if (!string.IsNullOrWhiteSpace(Subtitle))
{
<p>@Subtitle</p>
}
</header>
@code {
[Parameter] public string Title { get; set; } = string.Empty;
[Parameter] public string? Subtitle { get; set; }
}
Gebruik in Components/Pages/Home.razor:
@page "/"
<PageTitle>Blazor vanaf nul</PageTitle>
<SectionHeader
Title="Blazor vanaf nul"
Subtitle="Hoofdstuk 3 gaat over componenten." />
Klein voorbeeld, groot principe: een component moet via parameters leesbaar zijn.
Stap 2: Maak gedrag expliciet met parameters
Laten we een herbruikbare knop maken.
Components/Common/AppButton.razor:
<button class="app-button @VariantCssClass" @onclick="OnClick">
@Text
</button>
@code {
[Parameter] public string Text { get; set; } = "Button";
[Parameter] public string Variant { get; set; } = "primary";
[Parameter] public EventCallback OnClick { get; set; }
private string VariantCssClass => Variant.ToLowerInvariant() switch
{
"secondary" => "app-button--secondary",
"danger" => "app-button--danger",
_ => "app-button--primary"
};
}
Gebruik:
@code {
private int _savedCount;
private void Save()
{
_savedCount++;
}
}
<AppButton Text="Save" Variant="primary" OnClick="Save" />
<p>Opgeslagen @_savedCount keer.</p>
Belangrijkste punt: contractontwerp.
- Houd parameters klein en helder
- Gebruik expliciete namen, geen verborgen magie
- Geef veilige defaults
Stap 3: Gebruik RenderFragment voor compositie
Met RenderFragment kan een parent UI-blokken meegeven aan een child.
Maak Components/Common/Card.razor:
<article class="card">
<header class="card__header">@Title</header>
<section class="card__body">
@ChildContent
</section>
</article>
@code {
[Parameter] public string Title { get; set; } = string.Empty;
[Parameter] public RenderFragment? ChildContent { get; set; }
}
Gebruik:
<Card Title="Roadmap">
<ul>
<li>Componenten</li>
<li>Data binding</li>
<li>Routing</li>
</ul>
</Card>
Zo bouw je consistente layout zonder overal dezelfde wrapper-markup te herhalen.
Stap 4: Kies compositie boven gigantische pagina’s
Wordt een pagina te groot? Splits op verantwoordelijkheid:
ProfileSummaryvoor het bovenste profielblokProfileStatsvoor metricsProfileActivityListvoor recente activiteit
De pagina wordt dan orkestratie, niet implementatiedetail.
Stap 5: Houd markup en logica in balans
Voor simpele componenten is inline @code prima.
Voor grotere componenten, gebruik code-behind:
UserCard.razorUserCard.razor.cs
Dat houdt markup en C# logica allebei leesbaar.
Stap 6: Praktische mappenstructuur
Een structuur die goed schaalt:
Components/Pages/-> routeerbare pagina’sComponents/Layout/-> app-shell en navigatieComponents/Common/-> gedeelde generieke bouwstenenComponents/Features/<FeatureName>/-> feature-specifieke componenten
Veelgemaakte fouten in vroege Blazor-projecten
- Te veel parameters in plaats van een dedicated viewmodel
- Businessregels direct in pagina-componenten
- Eén “god component” met honderden regels
- Markup-patronen herhalen in plaats van kleine herbruikbare componenten maken
Volgende hoofdstuk
In Hoofdstuk 4 focussen we op data binding en events: @bind, event handling, trade-offs van two-way binding en patronen voor voorspelbare state.