Blazor vanaf nul: Hoofdstuk 3 — Componenten die schalen

· 3 min lezen

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:

  • ProfileSummary voor het bovenste profielblok
  • ProfileStats voor metrics
  • ProfileActivityList voor 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.razor
  • UserCard.razor.cs

Dat houdt markup en C# logica allebei leesbaar.


Stap 6: Praktische mappenstructuur

Een structuur die goed schaalt:

  • Components/Pages/ -> routeerbare pagina’s
  • Components/Layout/ -> app-shell en navigatie
  • Components/Common/ -> gedeelde generieke bouwstenen
  • Components/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.