带有ChildContent RenderFragment的Blazor怪异

时间:2020-10-29 00:00:04

标签: blazor blazor-server-side

这个问题已经被问到here,但是重新提交了一个更清晰的示例(希望如此)。

当尝试确定Blazor重新渲染和更新状态的时间以及方式时,我注意到了这种奇怪的行为。

采用以下简单组件Test1Component

@if (_show) {
    <h3>Test1Component</h3>
}

@code {
    private bool _show = true;

    public void Show() {
        _show = true;
    }

    public void Hide() {
        _show = false;
    }
}

在另一个组件中使用时,调用ShowHide不会执行任何操作:

<Test1Component @ref="_test1Component"></Test1Component>

<button type="button" @onclick="(() => { if (_test1Component != null) _test1Component.Hide(); })">Hide Test</button>
<button type="button" @onclick="(() => { if (_test1Component != null) _test1Component.Show(); })">Show Test</button>

@code{
    Test1Component _test1Component;
}

为了使其正常工作,必须将StateHasChanged()添加到ShowHide方法中。但是,如果我们将实现更改为包括RenderFragment,则ShowHide方法神秘地开始工作。

@if (_show) {
    <h3>@ChildContent</h3>
}

@code {
    private bool _show = true;
    [Parameter] public RenderFragment ChildContent { get; set; }

    public void Show() {
        _show = true;
    } 

    public void Hide() {
        _show = false;
    }
}

ShowHide方法现在可以使用,即使已更改的只是添加RenderFragment

<Test1Component @ref="_test1Component">Test1Component</Test1Component>

<button type="button" @onclick="(() => { if (_test1Component != null) _test1Component.Hide(); })">Hide Test</button>
<button type="button" @onclick="(() => { if (_test1Component != null) _test1Component.Show(); })">Show Test</button>

@code{
    Test1Component _test1Component;
}

我怀疑Blazor由于RenderFragment在后​​台以某种方式注册了此组件,正在内部跟踪其状态并在更新时自动触发StateHasChanged

然后,这是一个问题,在这种情况下,您是否在实践中使用StateHadChanged方法来更新状态,或者在包含RenderFragment时依靠自动保留的状态?

有人知道吗1.为什么会发生? 2.使它工作的幕后到底发生了什么?我只是通过非常有条理地尝试找出从头开始触发更新的最佳方法来注意到这一点,但是从Blazor开始,这导致了一些混乱,因为某些组件可以正常工作,而另一些组件如果没有{{1} }被称为行为似乎是随机的,有时没有韵律或理由。显然,现在开始知道为什么会发生这种情况。

1 个答案:

答案 0 :(得分:0)

当您的组件中没有Parameters时,渲染器将正确假定没有任何更改,并且在单击button

导致的渲染过程中也无需重新渲染它

添加RenderFragment参数会强制Blazor的手-它必须进行渲染,因为它无法检测该参数是否已更改。

调用子组件的公共方法的做法是可疑的-如果您仅包含诸如bool Hide之类的参数,并从父项中设置它就可以正常工作。