Poznámka:
Přístup k této stránce vyžaduje autorizaci. Můžete se zkusit přihlásit nebo změnit adresáře.
Přístup k této stránce vyžaduje autorizaci. Můžete zkusit změnit adresáře.
Bez zachování stavu součásti se stav použitý během předrenderingu ztratí a při plném načtení aplikace se musí znovu vytvořit. Pokud se stav vytvoří asynchronně, může UI poblikávat, protože se prerenderované UI nahradí při opětovném renderování komponenty.
Zvažte následující komponentu PrerenderedCounter1 čítače. Komponent nastavuje počáteční náhodnou hodnotu počítadla během předrendurace v metodě životního cyklu OnInitialized. Když se komponenta pak vykreslí interaktivně, počáteční hodnota počtu se při druhém spuštění nahradí OnInitialized .
PrerenderedCounter1.razor:
@page "/prerendered-counter-1"
@inject ILogger<PrerenderedCounter1> Logger
<PageTitle>Prerendered Counter 1</PageTitle>
<h1>Prerendered Counter 1</h1>
<p role="status">Current count: @currentCount</p>
<button class="btn btn-primary" @onclick="IncrementCount">Click me</button>
@code {
private int currentCount;
protected override void OnInitialized()
{
currentCount = Random.Shared.Next(100);
Logger.LogInformation("currentCount set to {Count}", currentCount);
}
private void IncrementCount() => currentCount++;
}
Poznámka:
Pokud aplikace přijme interaktivní směrování a k stránce se přistupuje prostřednictvím interního rozšířené navigace, nedojde k předrenderingu. Proto musíte pro komponentu PrerenderedCounter1 provést úplné znovunačtení stránky, abyste viděli následující výstup. Další informace najdete v části Interaktivní směrování a předběžné vykreslování.
Spusťte aplikaci a zkontrolujte protokolování z komponenty. Následující je ukázkový výstup.
info: BlazorSample.Components.Pages.PrerenderedCounter1[0]
currentCount set to 41
info: BlazorSample.Components.Pages.PrerenderedCounter1[0]
currentCount set to 92
První zaznamenané počítání proběhne během předrendrování. Počet je znovu nastaven po předběžném vykreslení, když je komponenta znovu vykreslena. V uživatelském rozhraní dochází také k blikání, když se počet aktualizuje z 41 na 92.
Chcete-li zachovat počáteční hodnotu počítadla během vykreslování, Blazor podporuje uložení stavu na vykreslené stránce pomocí služby PersistentComponentState (a pro komponenty vložené do stránek nebo zobrazení aplikací Razor Pages nebo MVC aplikací, Pomocník značek pro uchování stavu komponent).
Inicializací komponentů se stejným stavem, jaký byl použit během předrenderování, jsou jakékoliv nákladné kroky inicializace provedeny pouze jednou. Vykreslené uživatelské rozhraní se také shoduje s předem vykresleným uživatelským rozhraním, takže v prohlížeči nedojde k žádnému blikání.
Trvalý prerenderovaný stav se přenese do klienta, kde se používá k obnovení stavu komponenty. Při vykreslování na straně klienta (CSR, InteractiveWebAssembly) jsou data vystavena prohlížeči a nesmí obsahovat citlivé nebo soukromé informace. Během interaktivního vykreslování na straně serveru (interaktivní SSR, InteractiveServer) zajišťuje ASP.NET Core Data Protection bezpečný přenos dat. Režim vykreslování InteractiveAuto kombinuje interaktivitu WebAssembly a serveru, proto je nutné zvážit vystavení dat prohlížeči, podobně jako v případě CSR.
Chcete-li zachovat předvyrenderovaný stav, použijte [PersistentState] atribut pro uložení stavu ve vlastnostech. Vlastnosti s tímto atributem se při předkreslování automaticky zachovají pomocí PersistentComponentState služby. Stav se načte, když se komponenta vykreslí interaktivně nebo se vytvoří instance služby.
Ve výchozím nastavení jsou vlastnosti serializovány pomocí System.Text.Json serializátoru s výchozím nastavením a jsou trvalé v předkončítaném HTML. Serializace není bezpečná a vyžaduje zachování použitých typů. Další informace naleznete v tématu Konfigurace trimmeru pro ASP.NET Core Blazor.
Následující komponenta čítače uchovává stav čítače během přerendrování a načítá stav pro inicializaci komponenty.
- Atribut
[PersistentState]se použije na typ s možnouinthodnotou null (CurrentCount). - Stav čítače se přiřadí, když
nullje vOnInitialized, a obnoví se automaticky, když se komponenta interaktivně vykreslí.
PrerenderedCounter2.razor:
@page "/prerendered-counter-2"
@inject ILogger<PrerenderedCounter2> Logger
<PageTitle>Prerendered Counter 2</PageTitle>
<h1>Prerendered Counter 2</h1>
<p role="status">Current count: @CurrentCount</p>
<button class="btn btn-primary" @onclick="IncrementCount">Click me</button>
@code {
[PersistentState]
public int? CurrentCount { get; set; }
protected override void OnInitialized()
{
if (CurrentCount is null)
{
CurrentCount = Random.Shared.Next(100);
Logger.LogInformation("CurrentCount set to {Count}", CurrentCount);
}
else
{
Logger.LogInformation("CurrentCount restored to {Count}", CurrentCount);
}
}
private void IncrementCount() => CurrentCount++;
}
Když se komponenta spouští, CurrentCount je nastaven pouze jednou během předběžného vykreslování. Hodnota je obnovena, když je komponenta znovu vykreslena. Následující je ukázkový výstup.
Poznámka:
Pokud aplikace přijme interaktivní směrování a k stránce se přistupuje prostřednictvím interního rozšířené navigace, nedojde k předrenderingu. Proto musíte pro komponentu znovu načíst celou stránku, abyste viděli následující výstup. Další informace najdete v části Interaktivní směrování a předběžné vykreslování.
info: BlazorSample.Components.Pages.PrerenderedCounter2[0]
CurrentCount set to 96
info: BlazorSample.Components.Pages.PrerenderedCounter2[0]
CurrentCount restored to 96
V následujícím příkladu serializuje stav pro více komponent stejného typu:
- Vlastnosti anotované atributem
[PersistentState]jsou serializovány během předrenderingu. -
Atribut
@keydirektivy slouží k zajištění správného přidružení stavu k instanci komponenty. - Vlastnost
Elementse inicializuje vOnInitializedmetodě životního cyklu , aby se zabránilo výjimkám nulového odkazu, podobně jako se odkazy null vyhýbají parametrům dotazu a datům formuláře.
PersistentChild.razor:
<div>
<p>Current count: @Element.CurrentCount</p>
<button class="btn btn-primary" @onclick="IncrementCount">Click me</button>
</div>
@code {
[PersistentState]
public State Element { get; set; }
protected override void OnInitialized()
{
Element ??= new State();
}
private void IncrementCount()
{
Element.CurrentCount++;
}
private class State
{
public int CurrentCount { get; set; }
}
}
Parent.razor:
@page "/parent"
@foreach (var element in elements)
{
<PersistentChild @key="element.Name" />
}
Serializace stavu pro služby
V následujícím příkladu serializuje stav pro službu injektáž závislostí:
- Vlastnosti anotované atributem
[PersistentState]jsou serializovány během předrenderingu a deserializovány, když se aplikace stane interaktivní. - Metoda rozšíření RegisterPersistentService se používá k registraci služby pro uchování. Režim vykreslení je povinný, protože režim vykreslení nelze odvodit z typu služby. Použijte některou z následujících hodnot:
-
RenderMode.Server: Služba je k dispozici pro interaktivní režim vykreslování serveru. -
RenderMode.Webassembly: Služba je k dispozici pro interaktivní režim vykreslování WebAssembly. -
RenderMode.InteractiveAuto: Služba je k dispozici pro režimy interaktivního serveru i interaktivního webového sestavení, pokud se komponenta v některém z těchto režimů vykresluje.
-
- Služba se inicializuje během interaktivního režimu vykreslování a vlastnosti označené atributem
[PersistentState]jsou deserializovány.
Poznámka:
Podporují se pouze trvalé služby s vymezeným oborem.
Serializované vlastnosti jsou identifikovány ze skutečné instance služby:
- Tento přístup umožňuje označit abstrakci jako trvalou službu.
- Umožňuje skutečné implementace být interními nebo různými typy.
- Podporuje sdílený kód v různých sestaveních.
- Výsledkem je, že každá instance zobrazí stejné vlastnosti.
Následující služba čítače, CounterTracker, označuje aktuální vlastnost count, CurrentCount, s atributem [PersistentState]. Vlastnost je serializována během předběžného vykreslování a deserializována, když se aplikace stane interaktivní, všude, kde je služba vložena.
CounterTracker.cs:
public class CounterTracker
{
[PersistentState]
public int CurrentCount { get; set; }
public void IncrementCount()
{
CurrentCount++;
}
}
V souboru Program zaregistrujte scopovanou službu a zaregistrujte službu pro perzistenci s RegisterPersistentService. V následujícím příkladu je služba CounterTracker dostupná pro režim Interaktivní server a Interaktivní WebAssembly, pokud se komponenta vykresluje v některém z těchto režimů, protože je zaregistrována v RenderMode.InteractiveAuto.
Pokud daný soubor ještě nepoužívá obor názvů Program, přidejte na jeho začátek následující příkaz: Microsoft.AspNetCore.Components.Web.
using Microsoft.AspNetCore.Components.Web;
Kde jsou služby zaregistrované v Program souboru:
builder.Services.AddScoped<CounterTracker>();
builder.Services.AddRazorComponents()
.RegisterPersistentService<CounterTracker>(RenderMode.InteractiveAuto);
CounterTracker Vložte službu do komponenty a použijte ji k zvýšení čítače. Pro demonstrační účely v následujícím příkladu je hodnota vlastnosti služby CurrentCount nastavena na 10 pouze během předkreslování.
Pages/Counter.razor:
@page "/counter"
@inject CounterTracker CounterTracker
<PageTitle>Counter</PageTitle>
<h1>Counter</h1>
<p>Rendering: @RendererInfo.Name</p>
<p role="status">Current count: @CounterTracker.CurrentCount</p>
<button class="btn btn-primary" @onclick="IncrementCount">Click me</button>
@code {
protected override void OnInitialized()
{
if (!RendererInfo.IsInteractive)
{
CounterTracker.CurrentCount = 10;
}
}
private void IncrementCount()
{
CounterTracker.IncrementCount();
}
}
Chcete-li použít předchozí komponentu k předvedení zachování počtu 10 v CounterTracker.CurrentCount, přejděte na komponentu a aktualizujte prohlížeč, který aktivuje předdekreslování. Při předkreslování se krátce zobrazí RendererInfo.Name označení "Static" před zobrazením "Server" po konečném vykreslení. Počítadlo začíná na 10.
PersistentComponentState Použití služby přímo místo deklarativního modelu
Jako alternativu k použití deklarativního modelu pro zachování stavu s atributem[PersistentState] můžete použít PersistentComponentState přímo službu, která nabízí větší flexibilitu pro komplexní scénáře trvalosti stavu. Zavolejte PersistentComponentState.RegisterOnPersisting pro registraci zpětného volání k zachování stavu komponenty během předrenderování. Stav se načte, když se komponenta vykreslí interaktivně. Proveďte volání na konci inicializačního kódu, abyste se vyhnuli možné kolizi během ukončení aplikace.
Následující příklad komponenty s čítačem uchovává stav čítače během předběžného vykreslování a načítá stav pro inicializaci komponenty.
PrerenderedCounter3.razor:
@page "/prerendered-counter-3"
@implements IDisposable
@inject ILogger<PrerenderedCounter3> Logger
@inject PersistentComponentState ApplicationState
<PageTitle>Prerendered Counter 3</PageTitle>
<h1>Prerendered Counter 3</h1>
<p role="status">Current count: @currentCount</p>
<button class="btn btn-primary" @onclick="IncrementCount">Click me</button>
@code {
private int currentCount;
private PersistingComponentStateSubscription persistingSubscription;
protected override void OnInitialized()
{
if (!ApplicationState.TryTakeFromJson<int>(
nameof(currentCount), out var restoredCount))
{
currentCount = Random.Shared.Next(100);
Logger.LogInformation("currentCount set to {Count}", currentCount);
}
else
{
currentCount = restoredCount!;
Logger.LogInformation("currentCount restored to {Count}", currentCount);
}
// Call at the end to avoid a potential race condition at app shutdown
persistingSubscription = ApplicationState.RegisterOnPersisting(PersistCount);
}
private Task PersistCount()
{
ApplicationState.PersistAsJson(nameof(currentCount), currentCount);
return Task.CompletedTask;
}
private void IncrementCount() => currentCount++;
void IDisposable.Dispose() => persistingSubscription.Dispose();
}
Když se komponenta spouští, currentCount je nastaven pouze jednou během předběžného vykreslování. Hodnota je obnovena, když je komponenta znovu vykreslena. Následující je ukázkový výstup.
Poznámka:
Pokud aplikace přijme interaktivní směrování a k stránce se přistupuje prostřednictvím interního rozšířené navigace, nedojde k předrenderingu. Proto musíte pro komponentu znovu načíst celou stránku, abyste viděli následující výstup. Další informace najdete v části Interaktivní směrování a předběžné vykreslování.
info: BlazorSample.Components.Pages.PrerenderedCounter3[0]
currentCount set to 96
info: BlazorSample.Components.Pages.PrerenderedCounter3[0]
currentCount restored to 96
Aby bylo zachováno předem vykreslené staví, rozhodněte se, který stav chcete uchovat pomocí služby PersistentComponentState. PersistentComponentState.RegisterOnPersisting zaregistruje zpětné volání pro zachování stavu komponenty během předrenderingu. Stav se načte, když se komponenta vykreslí interaktivně. Proveďte volání na konci inicializačního kódu, abyste se vyhnuli možné kolizi během ukončení aplikace.
Následující příklad komponenty s čítačem uchovává stav čítače během předběžného vykreslování a načítá stav pro inicializaci komponenty.
PrerenderedCounter2.razor:
@page "/prerendered-counter-2"
@implements IDisposable
@inject ILogger<PrerenderedCounter2> Logger
@inject PersistentComponentState ApplicationState
<PageTitle>Prerendered Counter 2</PageTitle>
<h1>Prerendered Counter 2</h1>
<p role="status">Current count: @currentCount</p>
<button class="btn btn-primary" @onclick="IncrementCount">Click me</button>
@code {
private int currentCount;
private PersistingComponentStateSubscription persistingSubscription;
protected override void OnInitialized()
{
if (!ApplicationState.TryTakeFromJson<int>(
nameof(currentCount), out var restoredCount))
{
currentCount = Random.Shared.Next(100);
Logger.LogInformation("currentCount set to {Count}", currentCount);
}
else
{
currentCount = restoredCount!;
Logger.LogInformation("currentCount restored to {Count}", currentCount);
}
// Call at the end to avoid a potential race condition at app shutdown
persistingSubscription = ApplicationState.RegisterOnPersisting(PersistCount);
}
private Task PersistCount()
{
ApplicationState.PersistAsJson(nameof(currentCount), currentCount);
return Task.CompletedTask;
}
void IDisposable.Dispose() => persistingSubscription.Dispose();
private void IncrementCount() => currentCount++;
}
Když se komponenta spouští, currentCount je nastaven pouze jednou během předběžného vykreslování. Hodnota je obnovena, když je komponenta znovu vykreslena. Následující je ukázkový výstup.
Poznámka:
Pokud aplikace přijme interaktivní směrování a k stránce se přistupuje prostřednictvím interního rozšířené navigace, nedojde k předrenderingu. Proto musíte pro komponentu znovu načíst celou stránku, abyste viděli následující výstup. Další informace najdete v části Interaktivní směrování a předběžné vykreslování.
info: BlazorSample.Components.Pages.PrerenderedCounter2[0]
currentCount set to 96
info: BlazorSample.Components.Pages.PrerenderedCounter2[0]
currentCount restored to 96
Rozšiřitelnost serializace pro trvalý stav součásti
Implementujte vlastní serializátor s PersistentComponentStateSerializer<T>. Bez registrovaného vlastního serializátoru se serializace vrátí do existující serializace JSON.
Vlastní serializátor je zaregistrovaný v souboru aplikace Program . V následujícím příkladu je pro typ CustomUserSerializer registrováno TUser.
builder.Services.AddSingleton<PersistentComponentStateSerializer<TUser>,
CustomUserSerializer>();
Typ se automaticky zachová a obnoví pomocí vlastního serializátoru:
[PersistentState]
public User? CurrentUser { get; set; } = new();
Komponenty vložené do stránek a zobrazení (Razor Stránky/MVC)
Pro komponenty vložené do stránky nebo zobrazení aplikace Razor Pages nebo MVC musíte přidat Persist Component State Tag Helper s <persist-component-state /> HTML tagem uvnitř uzavíracího </body> tagu rozvržení aplikace. Toto je vyžadováno pouze pro Razor Pages a MVC aplikace. Pro další informace viz Persist Component State Tag Helper in ASP.NET Core.
Pages/Shared/_Layout.cshtml:
<body>
...
<persist-component-state />
</body>
Interaktivní směrování a předrendering
Pokud komponenta Routes nedefinuje režim vykreslování, aplikace používá interaktivitu a navigaci pro jednotlivé stránky nebo komponenty. Při použití navigace na stránce nebo komponentě se interní navigace zpracovává vylepšeným směrováním po interaktivní aplikaci. "Interní navigace" v tomto kontextu znamená, že cíl adresy URL navigační události je Blazor koncový bod uvnitř aplikace.
Blazor podporuje zpracování stavu trvalých součástí během rozšířené navigace. Stav trvalý během rozšířené navigace může číst interaktivní komponenty na stránce.
Ve výchozím nastavení je trvalý stav součásti načtený pouze interaktivními komponentami, když jsou původně načteny na stránku. Zabráníte tak přepsání důležitých stavů, jako jsou data v upraveném webovém formuláři, pokud po načtení komponenty dojde k dalším rozšířeným událostem navigace na stejnou stránku.
Pokud jsou data určená jen pro čtení a nemění se často, povolte při rozšířené navigaci možnost povolit aktualizace nastavením AllowUpdates = trueatributu[PersistentState]. To je užitečné pro scénáře, jako je zobrazení dat uložených v mezipaměti, která jsou náročná na načtení, ale často se nemění. Následující příklad ukazuje použití AllowUpdates dat předpovědi počasí:
[PersistentState(AllowUpdates = true)]
public WeatherForecast[]? Forecasts { get; set; }
protected override async Task OnInitializedAsync()
{
Forecasts ??= await ForecastService.GetForecastAsync();
}
Pokud chcete během předkončování přeskočit stav obnovení, nastavte RestoreBehavior na SkipInitialValue:
[PersistentState(RestoreBehavior = RestoreBehavior.SkipInitialValue)]
public string NoPrerenderedData { get; set; }
Pokud chcete během opětovného připojení přeskočit obnovení stavu, nastavte RestoreBehavior hodnotu SkipLastSnapshot. To může být užitečné k zajištění nových dat po opětovném připojení:
[PersistentState(RestoreBehavior = RestoreBehavior.SkipLastSnapshot)]
public int CounterNotRestoredOnReconnect { get; set; }
Volání PersistentComponentState.RegisterOnRestoring pro registraci zpětného volání pro imperativní řízení způsobu obnovení stavu, podobně jako PersistentComponentState.RegisterOnPersisting poskytuje úplnou kontrolu nad tím, jak je stav zachován.
Služba PersistentComponentState funguje pouze při prvotním načtení stránky, nikoli během interních událostí vylepšené navigace na stránce.
Pokud aplikace provede plnou (neposílenou) navigaci na stránku využívající stav přetrvávajících komponent, přetrvávající stav je aplikaci k dispozici pro použití, když se stane interaktivní.
Pokud již byl vytvořen interaktivní okruh a rozšířená navigace se provádí na stránce využívající trvalý stav součásti, stav není k dispozici v existujícím okruhu, aby komponenta používala. Pro předběžné vykreslení požadavku na interní stránku nic neexistuje a služba PersistentComponentState si není vědoma, že došlo ke zlepšené navigaci. Neexistuje žádný mechanismus pro doručování aktualizací stavu komponent, které už běží v existujícím okruhu. Důvodem je to, že Blazor podporuje pouze předávání stavu ze serveru klientovi v době, kdy se modul runtime inicializuje, ne po spuštění modulu runtime.
Zakázání vylepšené navigace, které snižuje výkon, ale zároveň předchází problému s načítáním stavu s PersistentComponentState pro interní požadavky na stránky, je popsáno v směrování a navigaci ASP.NET CoreBlazor. Případně aktualizujte aplikaci na .NET 10 nebo novější, kde Blazor podporuje zpracování stavu trvalých komponent při rozšířené navigaci.