Komponenten är Blazors atom. Vi går igenom Razor-syntaxen, hur man skapar egna komponenter, skickar in parametrar och förstår livscykeln.
Razor är ett sätt att blanda HTML och C# i samma fil. Allting som börjar med @ är C#; resten är HTML.
<h1>Välkommen, @anvandarnamn</h1>
<p>Klockan är @DateTime.Now.ToString("HH:mm")</p>
@if (loggedIn)
{
<p>Du är inloggad.</p>
}
else
{
<a href="/login">Logga in</a>
}
<ul>
@foreach (var item in items)
{
<li>@item.Namn — @item.Pris.ToString("C")</li>
}
</ul>
| Konstruktion | Användning |
|---|---|
@variabel | Skriv ut värdet inline |
@(uttryck) | Tvinga parentes för komplext uttryck |
@if / @foreach / @switch | C#-kontrollflöde i markup |
@{ /* kod */ } | Block av C# utan output |
@@text | Literal @-tecken (escape) |
En komponent är en .razor-fil. Den består typiskt av tre delar:
@* Components/UserCard.razor *@
@* 1. Direktiv — @page, @inject, @using *@
@using BlazorApp.Models
@* 2. Markup med inbäddad C# *@
<div class="card">
<h3>@User.FullName</h3>
<p>@User.Email</p>
<button @onclick="ShowDetails">Visa mer</button>
</div>
@* 3. Code block — fält, parametrar, metoder *@
@code {
[Parameter, EditorRequired] public User User { get; set; } = default!;
[Parameter] public EventCallback<User> OnDetailsRequested { get; set; }
private Task ShowDetails() => OnDetailsRequested.InvokeAsync(User);
}
UserCard.razor blir taggen <UserCard /> i andra komponenter. Mappnamnet syns inte i taggen, men @using behövs för att hitta komponenter i andra namespace.
@code {
[Parameter] public string Title { get; set; } = "";
[Parameter] public int Count { get; set; }
[Parameter, EditorRequired] public User User { get; set; } = default!;
[Parameter(CaptureUnmatchedValues = true)]
public IDictionary<string, object>? Extra { get; set; }
}
Användning i förälder:
<UserCard User="aktivAnvandare" Title="VIP-kund" Count="3" />
@* Card.razor *@
<div class="card">
<div class="card-header">@Header</div>
<div class="card-body">@ChildContent</div>
</div>
@code {
[Parameter] public RenderFragment? Header { get; set; }
[Parameter] public RenderFragment? ChildContent { get; set; }
}
Använd komponenten med innehåll mellan taggarna:
<Card>
<Header><h2>Min titel</h2></Header>
<ChildContent>
<p>Här är innehållet i kortet.</p>
<button>Klick</button>
</ChildContent>
</Card>
Blazor anropar speciella metoder vid bestämda tidpunkter. De viktigaste:
| Metod | Anropas | Typisk användning |
|---|---|---|
OnInitialized / OnInitializedAsync | En gång när komponenten skapas | Hämta initial data |
OnParametersSet / Async | När parametrar har satts (även första gången) | Reagera på ändrade input-värden |
OnAfterRender(firstRender) | Efter att DOM:en uppdaterats | JS-interop, fokus, externa bibliotek |
Dispose | När komponenten tas bort | Städa events, timers, subscriptions |
@code {
private List<Product> products = new();
protected override async Task OnInitializedAsync()
{
products = await Http.GetFromJsonAsync<List<Product>>("api/products")
?? new();
}
protected override void OnParametersSet()
{
// Körs varje gång CategoryId ändras utifrån
FilterProducts();
}
}
OnInitialized (utan Async). Använd alltid OnInitializedAsync för datahämtning.
För större komponenter kan koden flyttas till en partial class i en separat .razor.cs-fil:
// Components/UserCard.razor.cs
namespace BlazorApp.Components;
public partial class UserCard
{
[Parameter, EditorRequired] public User User { get; set; } = default!;
private async Task ShowDetails()
{
// logik här
}
}
I UserCard.razor behövs då bara markup. Detta gör större komponenter mer lättlästa och underlättar enhetstester.
Lös övningarna självständigt. Det finns inget facit — lärandet sker i processen.
Type (success/warning/error) och Message samt ha en stängknapp som tar bort sig själv. Visa minst 3 instanser med olika typer på en testsida.
UserCard som visar en användares namn och bild, samt accepterar valfritt innehåll via ChildContent. Använd den på en sida för att visa två kort med olika footer-innehåll.
.razor.cs-fil. Verifiera att allt fortfarande fungerar.
Button, Card, Modal, Badge. Varje komponent ska ha parametrar för utseende och ChildContent där det är vettigt. Visa dem alla på en demosida.
ArticleCard-komponent som tar in en Article-modell. Lägg till en filterknapp som visar/döljer artiklar utifrån kategori.