Dela via


Översikt över ASP.NET Core State Management Blazor

Den här artikeln och de andra artiklarna i den här noden beskriver vanliga metoder för att bevara en användares data medan de använder en app och över webbläsarsessioner, inklusive under server-förrendering.

Ett vanligt krav under Blazor apputveckling är delning av tillstånd mellan komponenter:

  • Förälder till barn: En föräldrakomponent skickar tillstånd till en barnkomponent via parametrar.
  • Barnkomponent till föräldrakomponent: En barnkomponent möjliggör databindning med sin tillstånd eller tillhandahåller tillstånd via återanrop.
  • Föräldrar till efterkommande: En förälder delar tillstånd med alla sina efterkommande med hjälp av kaskadvärden.
  • På appnivå: Övergripande tillstånd delas över hela appen med hjälp av konfigurerade tillståndstjänster.
  • Per krets: Tillstånd delas för en specifik krets med begränsade apptillståndstjänster.

Beständiga tillstånd kan behöva överleva siduppdateringar, återupptagna kretsar och prerendering. Tillstånd kräver ofta central hantering, spårning och testning. Platserna och teknikerna för att bevara tillståndet är mycket varierande.

Blazor ger inte omfattande, strukturerad tillståndshantering. Produkter och tjänster från tredje part som fungerar sömlöst med Blazor, till exempel Flux, Redux och MobX, uppfyller praktiskt taget alla appkrav.

Resten av den här artikeln beskriver allmänna strategier för tillståndshantering för alla typer av Blazor appar.

Tillståndshantering med hjälp av URL:en

För tillfälliga data som representerar navigeringstillståndet modellerar du data som en del av URL:en. Exempel på användartillstånd som modelleras i URL:en är:

  • ID för en visad entitet.
  • Det aktuella sidnumret i ett rutnät.

Innehållet i webbläsarens adressfält behålls:

  • Om användaren uppdaterar sidan manuellt.
  • Scenarier på serversidan: Om webbservern blir otillgänglig och användaren tvingas läsa in sidan igen för att ansluta till en annan server.

Information om hur du definierar URL-mönster med @page-direktivet finns i ASP.NET Core Blazor routning och navigering.

Containertjänst för minnesinternt tillstånd

Kapslade komponenter binder vanligtvis data med hjälp av länkad bindning enligt beskrivningen i ASP.NET Core Blazor-databindning. Kapslade och ej kapslade komponenter kan dela åtkomst till data med hjälp av en registrerad tillståndscontainer i minnet. En containerklass för anpassat tillstånd kan använda en tilldelningsbar Action för att meddela komponenter i olika delar av appen om tillståndsändringar. I följande exempel:

  • Ett par komponenter använder en tillståndscontainer för att spåra en egenskap.
  • En komponent i följande exempel är kapslad i den andra komponenten, men kapsling krävs inte för att den här metoden ska fungera.

Viktigt!

Exemplet i det här avsnittet visar hur du skapar en containertjänst för minnesinternt tillstånd, registrerar tjänsten och använder tjänsten i komponenter. Exemplet bevarar inte data utan vidare utveckling. För beständig lagring av data måste tillståndscontainern använda en underliggande lagringsmekanism som överlever när webbläsarminnet rensas. Detta kan åstadkommas med localStorage/sessionStorage eller någon annan teknik.

StateContainer.cs:

public class StateContainer
{
    private string? savedString;

    public string Property
    {
        get => savedString ?? string.Empty;
        set
        {
            savedString = value;
            NotifyStateChanged();
        }
    }

    public event Action? OnChange;

    private void NotifyStateChanged() => OnChange?.Invoke();
}

Appar på klientsidan (Program fil):

builder.Services.AddSingleton<StateContainer>();

Appar på serversidan (Program fil, ASP.NET Core i .NET 6 eller senare):

builder.Services.AddScoped<StateContainer>();

Appar på serversidan (Startup.ConfigureServices av Startup.cs, vanligtvis i .NET 6 eller tidigare):

services.AddScoped<StateContainer>();

Shared/Nested.razor:

@implements IDisposable
@inject StateContainer StateContainer

<h2>Nested component</h2>

<p>Nested component Property: <b>@StateContainer.Property</b></p>

<p>
    <button @onclick="ChangePropertyValue">
        Change the Property from the Nested component
    </button>
</p>

@code {
    protected override void OnInitialized()
    {
        StateContainer.OnChange += StateHasChanged;
    }

    private void ChangePropertyValue()
    {
        StateContainer.Property = 
            $"New value set in the Nested component: {DateTime.Now}";
    }

    public void Dispose()
    {
        StateContainer.OnChange -= StateHasChanged;
    }
}

StateContainerExample.razor:

@page "/state-container-example"
@implements IDisposable
@inject StateContainer StateContainer

<h1>State Container Example component</h1>

<p>State Container component Property: <b>@StateContainer.Property</b></p>

<p>
    <button @onclick="ChangePropertyValue">
        Change the Property from the State Container Example component
    </button>
</p>

<Nested />

@code {
    protected override void OnInitialized()
    {
        StateContainer.OnChange += StateHasChanged;
    }

    private void ChangePropertyValue()
    {
        StateContainer.Property = "New value set in the State " +
            $"Container Example component: {DateTime.Now}";
    }

    public void Dispose()
    {
        StateContainer.OnChange -= StateHasChanged;
    }
}

De föregående komponenterna implementerar IDisposable, och de OnChange ombuden avregistreras i de Dispose metoderna, som anropas av ramverket när komponenterna tas bort. Mer information finns i ASP.NET Core Razor komponenthantering.

Sammanhängande värden och parametrar

Använd sammanhängande värden och parametrar för att hantera tillstånd genom att flöda data från en överordnad Razor komponent till underordnade komponenter:

  • Hantera tillståndet över många komponenter.
  • Om det bara finns ett tillståndsobjekt på den översta nivån att bevara.

Sammanhängande värden på rotnivå med en CascadingValueSource<TValue> möjliggör Razor komponentprenumeranter att få meddelanden om ändrade kaskadvärden. Mer information och ett fungerande exempel finns i NotifyingDalek exempel i ASP.NET Core Blazor sammanhängande värden och parametrar.

Stöd för tillståndsändringar utanför Blazorsynkroniseringskontexten

När du använder en anpassad tillståndshanteringstjänst där du vill stötta tillståndsändringar utanför Blazor:s synkroniseringskontext (till exempel från en timer eller en bakgrundstjänst) måste alla konsumerande komponenter omsluta StateHasChanged-anropet i ComponentBase.InvokeAsync. Detta säkerställer att ändringsmeddelandet hanteras i återgivarens synkroniseringskontext.

När tillståndshanteringstjänsten inte anropar StateHasChanged på Blazorsynkroniseringskontext utlöses följande fel:

System.InvalidOperationException: "Den aktuella tråden är inte associerad med Dispatcher. Använd InvokeAsync() för att byta exekvering till Dispatcher när renderings- eller komponenttillståndet triggas.

Mer information och ett exempel på hur du åtgärdar det här felet finns i ASP.NET Core Razor komponentåtergivning.