Asp.net core 如何从另一个razor组件重新渲染razor组件
我似乎无法根据从另一个组件执行的操作重新渲染razor组件。例如: 假设我们有一个组件库“ComponentVariables”,其中定义了一个变量“buttonClickCount”,以跟踪按钮被单击的次数,以及增加变量的方法 ComponentVariables.cs 然后它被_Imports.razor中的所有组件继承,带有Asp.net core 如何从另一个razor组件重新渲染razor组件,asp.net-core,razor,blazor,Asp.net Core,Razor,Blazor,我似乎无法根据从另一个组件执行的操作重新渲染razor组件。例如: 假设我们有一个组件库“ComponentVariables”,其中定义了一个变量“buttonClickCount”,以跟踪按钮被单击的次数,以及增加变量的方法 ComponentVariables.cs 然后它被_Imports.razor中的所有组件继承,带有@inherits ComponentVariables home组件具有以下代码 家用剃须刀 @buttonClickCount 该按钮是在Clicker.raz
@inherits ComponentVariables
home组件具有以下代码
家用剃须刀
@buttonClickCount
该按钮是在Clicker.razor组件中创建的。以及引用组件库中的方法的onclick。和一个包含计数的div(也来自组件基)
响片剃须刀
点击我
@按钮计数
@代码
{
}
现在,home.razor和clicker.razor都在ComponentVariables.cs中使用相同的变量来显示值。但是,当我单击时,只有Clicker组件被重新命名。i、 e.主页始终显示0,而单击器随着您的单击而增加
非常感谢您的帮助。您使用了继承。因此,似乎您操作同一个变量是因为它们有名称,但实际上,它们都是具有唯一值的唯一实例 如果要在不同组件之间交换值,有三种方法。描述他们。根据您的描述,我建议使用AppState方法。我已经写了答案 我已经复制了之前答案的相关部分,并添加了一些新的想法 让我们首先定义
AppState
。此类使用.NET事件或委托在值更改时发出通知
public class AppState
{
private Int32 _clickCounter = 0;
public Int32 ClickCounter
{
get => _clickCounter;
set
{
_clickCounter = value;
AppStateChanged?.Invoke(nameof(ClickCounter), this);
}
}
public event AppStateChangedHandler AppStateChanged;
}
处理程序公共委托void AppStateChangedHandler(字符串propertyName,AppState)代码>。更改处理程序包括对象本身和已更改的propertyName
。如果更改是相关的,订阅事件的组件可以使用它进行筛选
AppState被添加到依赖项注入系统中。对于Blazor WASM,它应该是一个单例依赖项。不过,对于Blazor服务器,它应该是一个有范围的服务器
public static async Task Main(string[] args)
{
var builder = WebAssemblyHostBuilder.CreateDefault(args);
builder.RootComponents.Add<App>("#app");
...
builder.Services.AddSingleton(new AppState());
...
await builder.Build().RunAsync();
}
使用AppState中相应的属性,而不是递增(并读取)局部变量
为了简化对变更事件的订阅并减少每个组件中的样板文件,我们创建了一个名为AppStateAwareRecomponentBase
的抽象库。这应该是一个普通的.cs文件
public abstract class AppStateAwareComponentBase : ComponentBase, IDisposable
{
[Inject]
protected AppState AppState { get; private set; }
protected override void OnInitialized()
{
base.OnInitialized();
AppState.AppStateChanged += AppStateChanged;
}
protected abstract Boolean HandleAppStateChanged(String propertyName, AppState state);
private async void AppStateChanged(String propertyName, AppState state)
{
Boolean changesOccured = HandleAppStateChanged(propertyName, state);
if (changesOccured == true)
{
await InvokeAsync(StateHasChanged);
}
}
public void Dispose()
{
AppState.AppStateChanged -= AppStateChanged;
}
}
此类已订阅更改事件,但不知道如何准确处理它。因此,它有一个名为HandleAppStateChanged
的抽象方法,需要在以后的具体类中实现。此类确定布局更改是否是后续结果。如果需要布局更新,子调用将返回true
。父类(AppStateAwareComponentBase
)通过调用InvokeAsync(StateHasChanged)
启动布局更新
如果AppState
是通过[Inject]
注入的,并且IDisposable
的实现保证在从树中删除组件时删除对委托的订阅
我创建了一个CounterHeader
组件,作为从AppStateAwareComponentBase继承的类
@inherits AppStateAwareComponentBase
<span>Current App Global Counter: @_counter </span>
@code{
private Int32 _counter = 0;
protected override Boolean HandleAppStateChanged(String propertyName, AppState state)
{
if(propertyName != nameof(AppState.ClickCounter)) {
return false;
}
_counter = state.ClickCounter;
return true;
}
}
@继承AppStateAwareComponentBase
当前应用程序全局计数器:@\u计数器
@代码{
专用Int32_计数器=0;
受保护的重写布尔HandleAppStateChanged(字符串propertyName,AppState)
{
if(propertyName!=nameof(AppState.ClickCounter)){
返回false;
}
_计数器=状态。单击计数器;
返回true;
}
}
其他想法
这是“AppState”的基本版本。然而,对于所有这些状态转换都有类似的框架,或者您可以使用一种更解耦的方式,比如组件的消息总线,称为
每个应用程序可以有多个“状态”,如ShoopingCardState
,UserState
等,以将其拆分为不同的较小部分。您使用了继承。因此,看起来您操作同一个变量是因为它们有名称,但实际上,它们都是具有唯一值的唯一实例。也许,您可以描述一下使用这种方法想要实现什么?我开始更多地使用调试器,并注意到每个razor组件都调用了base。这意味着我怀疑你是对的。那么在这种情况下,我将如何在所有组件中引用相同的变量,并使它们随着所述变量的更新而动态变化?有三种方法来处理它。根据您的描述,我建议您使用AppState。我已经写了答案。或者你可以看一看,非常感谢!我只是浏览了这两个链接。它们看起来非常有用,尤其是appstate。然而,接下来的问题是,是否有可能根据变量的变化将重新渲染限制在特定组件上?因为这是我处境中最重要的部分。@VictoryObot,事件或代表呢<代码>
public static async Task Main(string[] args)
{
var builder = WebAssemblyHostBuilder.CreateDefault(args);
builder.RootComponents.Add<App>("#app");
...
builder.Services.AddSingleton(new AppState());
...
await builder.Build().RunAsync();
}
@page "/Counter"
@inject AppState appState
<h1>Counter</h1>
<p>Current count: @appState.ClickCounter</p>
<button class="btn btn-primary" @onclick="IncrementCount">Click me</button>
@code {
private void IncrementCount()
{
appState.ClickCounter++;
}
}
public abstract class AppStateAwareComponentBase : ComponentBase, IDisposable
{
[Inject]
protected AppState AppState { get; private set; }
protected override void OnInitialized()
{
base.OnInitialized();
AppState.AppStateChanged += AppStateChanged;
}
protected abstract Boolean HandleAppStateChanged(String propertyName, AppState state);
private async void AppStateChanged(String propertyName, AppState state)
{
Boolean changesOccured = HandleAppStateChanged(propertyName, state);
if (changesOccured == true)
{
await InvokeAsync(StateHasChanged);
}
}
public void Dispose()
{
AppState.AppStateChanged -= AppStateChanged;
}
}
@inherits AppStateAwareComponentBase
<span>Current App Global Counter: @_counter </span>
@code{
private Int32 _counter = 0;
protected override Boolean HandleAppStateChanged(String propertyName, AppState state)
{
if(propertyName != nameof(AppState.ClickCounter)) {
return false;
}
_counter = state.ClickCounter;
return true;
}
}