我想弄清楚当应用程序范围内的类(AppState模式)属性发生变化时,向组件发送重新呈现请求的最佳方法是什么。
继Chris Sainty的这篇博文之后,第三个例子正是我想要实现的。
有一个单例/作用域服务AppState,其主要目的是存储由几个组件使用的会话数据,当它的一个属性发生变化时调用事件操作,例如,在从外部api获取一些数据之后。然后,组件可以侦听该消息并调用StateHasChanged()
来重新呈现页面。
这工作,但我有几个问题的方法。
-
这是最好的方法还是有更合适的方法默认情况下在语言中实现的方式?无论是基于事件的通信还是整个AppState服务。我想这是一个相当普遍的问题,也许我错过了一些默认的功能,如
@bind
。 -
@implements IDisposable
有什么缺点吗?我明白为什么它需要被处理掉,但为什么我们不需要这样做,因为实例中,将一些数据绑定到输入字段以执行同样的事情吗?@bind
属性已经在引擎盖下处理了吗?
提前感谢,如果我错过了一些明显的东西,对不起,仍在学习Blazor的绳索。
这是最好的方法还是有更合适的方法默认情况下在语言中实现的方式?
对于不相关组件之间的通信,我们有不同的选项:
AppState
注册为作用域/单例。(注册和处理事件的额外开销)。AppState
作为razor
文件(代码示例如下)。- 遵循
MVVM
模式来存储state
,但这种方法有一个缺点,我们需要将每个view model
注入Scoped/Singleton
。(如果我们多次使用同一个组件,那么每个组件的状态将是相同的)。
您可以根据需要选择最好的。
AppState作为razor文件的例子(保存计数器的状态)
App.razor
看起来像这样:
<AppState>
<Router AppAssembly="@typeof(App).Assembly">
<Found Context="routeData">
<RouteView RouteData="@routeData" DefaultLayout="@typeof(MainLayout)" />
<FocusOnNavigate RouteData="@routeData" Selector="h1" />
</Found>
<NotFound>
<PageTitle>Not found</PageTitle>
<LayoutView Layout="@typeof(MainLayout)">
<p role="alert">Sorry, there's nothing at this address.</p>
</LayoutView>
</NotFound>
</Router>
</AppState>
和AppState.razor
看起来像这样:
<CascadingValue Value="this">
@ChildContent
</CascadingValue>
@code {
private int _count;
[Parameter]
public required RenderFragment ChildContent { get; set; }//use 'required' only if .net version is 7 & above
public int Count
{
get => _count;
set
{
_count = value;
StateHasChanged();
}
}
}
和计数器。Razor看起来像这样:
@page "/counter"
<PageTitle>Counter</PageTitle>
<h1>Counter</h1>
<p role="status">Current count: @State.Count</p>
<button class="btn btn-primary" @onclick="IncrementCount">Click me</button>
@code {
[CascadingParameter]
public required AppState State { get; set; }//use 'required' only if .net version is 7 & above
private void IncrementCount()
{
State.Count++;
}
}
@implements IDisposable有什么缺点吗?
不,只是额外的开销,我们需要手动处理所有未管理的资源。