可以在页面切换之间保留Blazor示例项目中Counter的状态吗?

时间:2019-12-01 15:15:30

标签: blazor

在服务器端Blazor和WebAssembly Blazor项目的默认示例项目中,每次在页面之间移动时,Counter示例都会重置为0。但是,在ASP.NET React示例项目中,计数器不会在页面切换之间重置。

Counter之类的组件是否可以保留Blazor中页面导航之间的状态(至少对于不进行任何服务器调用的WebAssembly项目)?

enter image description here

4 个答案:

答案 0 :(得分:2)

https://docs.microsoft.com/en-us/aspnet/core/blazor/state-management?view=aspnetcore-3.0#client-side-in-the-browser

中讨论了这种确切的情况

似乎Blazor并不开箱即用,但是您只需要使用localStoragesessionStorage

使用Blazor.Extensions.Storage NuGet软件包(https://github.com/BlazorExtensions/Storage):

@page "/counter"

@inject ISessionStorage SessionStorage
@using Blazor.Extensions.Storage.Interfaces

<h1>Counter</h1>

<p>Current count: @currentCount</p>

<button class="btn btn-primary" @onclick="IncrementCount">Click me</button>

@code {
    private int currentCount = 0;

    protected override async Task OnInitializedAsync()
    {
        currentCount = await SessionStorage.GetItem<int>("counter");
    }

    private async void IncrementCount()
    {
        currentCount++;
        await SessionStorage.SetItem<int>("counter", currentCount);
    }
}

答案 1 :(得分:1)

我在我的文章(适用于服务器端Blazor和客户端(WebAssembly)Blazor的文章)中对此进行了介绍:Implementing State Management In Blazor

使用以下代码添加一个名为CounterState.cs的类:

    public class CounterState
    {
        public int CurrentCount { get; set; }
    }

使用Dependency Injection在Startup.cs中注册此类:

services.AddScoped<CounterState>();

将以下代码添加到.razor代码页的顶部:

@inject CounterState CounterState

更改以下代码:

<p>Current count: @currentCount</p>

收件人:

<p>Current count: @CounterState.CurrentCount</p>

最后,将代码部分更改为以下内容:

@code {
    void IncrementCount()
    {
        // ** SESSION STATE
        int CurrentCount = CounterState.CurrentCount;
        CurrentCount++;
        // Set Current count on the Session State object
        CounterState.CurrentCount = CurrentCount;
    }
}

答案 2 :(得分:1)

对于服务器端Blazor,如果要在所有选项卡/客户端上保留/更新计数器值,则只需将其存储在静态变量中,然后在计数器值更改时重新呈现。

enter image description here

@page "/counter"

<h1>Static Counter</h1>

<p>Current static count: <span style="font-size:42px">@currentCount</span></p>

<button class="btn btn-primary" @onclick="IncrementCount">Click me</button>

@code {
    public static int currentCount = 0;

    private void IncrementCount()
    {
        currentCount++;

        StaticCount.FireUpdate();
    }

    protected override void OnInitialized()
    {
        base.OnInitialized();

        StaticCount.NewCounterValue += OnNewCounterValue;
    }

    void OnNewCounterValue(object sender, EventArgs e)
    {
        InvokeAsync(() =>
        {
            StateHasChanged();
        });
    }

    public void Dispose()
    {
        StaticCount.NewCounterValue -= OnNewCounterValue;
    }

}

@code{
    public static class StaticCount
    {
        public static event EventHandler NewCounterValue;

        public static void FireUpdate()
        {
            NewCounterValue?.Invoke(null, new EventArgs());
        }
    }
}

如果要在服务器重新启动之间保持该值,还可以使用(单个)服务来执行此操作,甚至将该值保留在数据库中。

答案 3 :(得分:0)

我写了一篇关于 Blazor 状态管理的回答,这里对此进行了研究:

https://stackoverflow.com/a/65609519/3850405

我的建议是内存状态容器服务。

示例:

StateContainer.cs

public class StateContainer
{
    public string Property { get; set; } = "Initial value from StateContainer";

    public event Action OnChange;

    public void SetProperty(string value)
    {
        Property = value;
        NotifyStateChanged();
    }

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

Program.Main (Blazor WebAssembly):

builder.Services.AddSingleton<StateContainer>();

Startup.ConfigureServices(Blazor 服务器):

services.AddSingleton<StateContainer>();

页面/Component1.razor

@page "/Component1"
@inject StateContainer StateContainer
@implements IDisposable

<h1>Component 1</h1>

<p>Component 1 Property: <b>@StateContainer.Property</b></p>

<p>
    <button @onclick="ChangePropertyValue">Change Property from Component 1</button>
</p>

<Component2 />

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

    private void ChangePropertyValue()
    {
        StateContainer.SetProperty($"New value set in Component 1 {DateTime.Now}");
    }

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

共享/Component2.razor

@inject StateContainer StateContainer
@implements IDisposable

<h2>Component 2</h2>

<p>Component 2 Property: <b>@StateContainer.Property</b></p>

<p>
    <button @onclick="ChangePropertyValue">Change Property from Component 2</button>
</p>

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

    private void ChangePropertyValue()
    {
        StateContainer.SetProperty($"New value set in Component 2 {DateTime.Now}");
    }

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

https://docs.microsoft.com/en-us/aspnet/core/blazor/state-management?view=aspnetcore-5.0&pivots=webassembly#in-memory-state-container-service-wasm