我在Blazor项目(.NET 5)上工作。我在组件渲染方面遇到了问题。我有一个内部包含ChildContent
的父组件。我是这样使用它的:
<ParentComponent>
<ChildComponent1 Title="Component1"></ChildComponent1>
<ChildComponent2 Title="Component2" SampleEnum="SampleEnum.Bar"></ChildComponent2>
</ParentComponent>
每个ChildComponent
都继承ChildComponentBase
:
public class ChildComponent1 : ChildComponentBase
{
// some code
}
ChildComponentBase
包含级联参数ParentComponent
和2个参数:其中一个是string
(Immutable for Blazor Change Detection API),另一个是enum
(不是不可变的),这只是一个例子。
public partial class ChildComponentBase
{
[CascadingParameter]
public ParentComponent Parent { get; set; } = default !;
[Parameter]
public string? Title { get; set; } // Immutable
[Parameter]
public SampleEnum SampleEnum { get; set; } // not Immutable
}
在ParentComponent
中,我使用了延迟渲染策略。Defer
组件看起来像这样,并在ParentComponent
中使用:
// This is used to move its body rendering to the end of the render queue so we can collect
// the list of child components first.
public class Defer : ComponentBase
{
[Parameter]
public RenderFragment ChildContent { get; set; }
protected override void BuildRenderTree( RenderTreeBuilder builder )
{
builder.AddContent( 0, ChildContent );
}
}
在我的第一次渲染项目中,我从ChildContent
中收集所有ChildComponent
,如下所示:
- 儿童组件底座剃须刀 *
@{
Parent.AddChild(this); // Parent is cascading parameter
}
然后调用回调函数来处理数据。ParentComponent
如下所示:* 父组件.剃刀 *
<CascadingValue Value="this" IsFixed>
@{
StartCollectingChildren();
}
@ChildContent
<Defer>
@{
FinishCollectingChildren();
ProcessDataAsync();
}
@foreach (var o in _childComponents)
{
<p>@o.Title</p>
}
</Defer>
</CascadingValue>
- 父组件.剃刀.cs*
public partial class ParentComponent
{
[Parameter]
public RenderFragment ChildContent { get; set; }
private List<ChildComponentBase> _childComponents = new();
private bool _firstRender = true;
private bool _collectingChildren; // Children might re-render themselves arbitrarily. We only want to capture them at a defined time.
protected async Task ProcessDataAsync()
{
if (_firstRender)
{
//imitating re-render just like it would be an async call
await InvokeAsync(StateHasChanged);
_firstRender = false;
}
}
public void AddChild(ChildComponentBase child)
{
_childComponents.Add(child);
}
private void StartCollectingChildren()
{
_childComponents.Clear();
_collectingChildren = true;
}
private void FinishCollectingChildren()
{
_collectingChildren = false;
}
}
由于调用回调-发生重新渲染。由于重新渲染,StartCollectingChildren()
再次被调用。这次在ParentComponent
的第二次渲染时,ChildComponent1
不会重新渲染,因为Blazor Change Detection API
跳过了它(因为它只包含一个不可变参数Title
,而ChildComponent2
还包含enum
参数)。
问题:如何重新渲染此ChildComponent1
?
我还添加了一个包含上述代码的Sample Project,以便您自己试用。
我尝试了所有我能在谷歌上找到的方法。我找到的最好的解决方法是在第一次渲染时缓存儿童集合,但它看起来很脏,可能会在未来导致问题。
1条答案
按热度按时间f3temu5u1#
快速解决问题的方法是修改级联并删除
IsFixed
。一旦这样做,捕获级联的任何组件都将始终呈现,因为
this
是一个对象,因此无法通过相等性检查。您还可以使用Guid级联驱动没有对象参数的子组件上的渲染事件。每当您希望在捕获级联的任何子组件上强制渲染时,请为Map的参数分配新的Guid。