【问题标题】:Conditionally pass renderfragments to components有条件地将渲染片段传递给组件
【发布时间】:2021-12-27 15:07:41
【问题描述】:

我正在尝试使用 @if 块有条件地将渲染片段传递给组件,但出现构建错误

Unrecognized child content inside component 'XXX'.

如果我有这样的父组件 AwesomeComponent

@code
{
    [Parameter] public RenderFragment ItemTemplate {get; set;}
    [Parameter] public RenderFragment AnotherItemTemplate {get; set;}
    [Parameter] public RenderFragment YetAnotherItemTemplate {get; set;}
}

然后有条件地想像这样渲染一个渲染片段:

<AwesomeComponent>

<ItemTemplate>
    // some code here
</ItemTemplate>

<AnotherItemTemplate>
    // blabla
</AnotherItemTemplate>

// This one i want to pass conditionally, the intuitive way is like this
@if (condition)
{
    <YetAnotherItemTemplate>
        // wooho
    </YetAnotherItemTemplate>
}

我收到Unrecognized child content inside component 错误。

我见过像this 这样的解决方案。但是,我也遇到了第三方组件的这些问题,因此我无法控制那里建议的可见性。此外,我不认为这是一个优雅的解决方案。

有没有人在类似的情况下找到了一种方法来处理所描述的条件渲染片段?我发现它在 Blazor 中是一个很大的限制。

【问题讨论】:

  • “我发现它在 Blazor 中是一个很大的限制。”问题不在于 Blazor

标签: c# .net razor blazor


【解决方案1】:

razor 语法让您可以混合搭配 html 和代码来处理各种条件渲染,Shaun 的回答就是一个很好的例子,说明这很容易做到。

但是,据我所知,问题是将子内容有条件地传递给您无法控制的组件。而且 Blazor 似乎不允许您以 razor 语法执行此操作。

假设组件很简单(或者你可以分解成方法),一个选项是两个渲染版本,一个有,一个没有:

@if (condition)
{
    <AwesomeComponent>
        <ItemTemplate>
            // some code here
        </ItemTemplate>
        <AnotherItemTemplate>
            // blabla
        </AnotherItemTemplate>
    </AwesomeComponent>
}
else
{
    <AwesomeComponent>
        <ItemTemplate>
            // some code here
        </ItemTemplate>
        <AnotherItemTemplate>
            // blabla
        </AnotherItemTemplate>
        <YetAnotherItemTemplate>
            // wooho
        </YetAnotherItemTemplate>
    </AwesomeComponent>
}

或者,您可以使用构建器执行此操作。一旦你有一些条件性的项目要包括在内,你就不得不手动进行。

@((RenderTreeBuilder b) =>
{
    b.OpenComponent<AwesomeComponent>(1);
    b.AddAddtribute(2, nameof(AwesomeComponent.ItemTemplate), itemContent);
    b.AddAddtribute(3, nameof(AwesomeComponent.AnotherItemTemplate), anotherItemContent);
    if (condition)
    {
        b.AddAddtribute(4, nameof(AwesomeComponent.YetAnotherItemTemplate), yetAnotherItemContent);
    }
    b.CloseComponent();
}) 

其中 itemContent 等是作为标记的 RenderFragments 或返回 RenderFragments 的方法。

【讨论】:

    【解决方案2】:

    你不能那样做。您的条件代码需要在组件中。然后将条件选择器作为Parameter 传递给组件。请参阅下面的代码。

    真棒组件

    <h3>AwesomeComponent</h3>
    
    @switch (FragmentToRender)
    {
        case 1:
        @this.ItemTemplate
        break;
        case 2:
        @this.AnotherItemTemplate
        break;
        case 3:
        @this.YetAnotherItemTemplate
        break;
        default:
        <span>No Component Selected</span>
        break;
    }
    @code
    {
        [Parameter] public RenderFragment? ItemTemplate {get; set;}
        [Parameter] public RenderFragment? AnotherItemTemplate {get; set;}
        [Parameter] public RenderFragment? YetAnotherItemTemplate {get; set;}
        [Parameter] public int FragmentToRender {get; set;}
    }
    

    演示页面

    @page "/"
    <h3>Awesome</h3>
    <div class="m-2">
        <button class="btn btn-primary" @onclick="() => this.ChangeComponent(1)">Display First Fragement</button>
        <button class="btn btn-secondary" @onclick="() => this.ChangeComponent(2)">Display Second Fragment</button>
        <button class="btn btn-dark" @onclick="() => this.ChangeComponent(3)">Display Third Fragment</button>
    </div>
    <div class="m-2">
        <AwesomeComponent FragmentToRender=this.componentToDisplay>
            <ItemTemplate>
                One
            </ItemTemplate>
            <AnotherItemTemplate>
                Two
            </AnotherItemTemplate>
            <YetAnotherItemTemplate>
                Three
            </YetAnotherItemTemplate>
        </AwesomeComponent>
    </div>
    
    @code {
        private int componentToDisplay;
    
        private void ChangeComponent(int value)
        => this.componentToDisplay = value;
    
    }
    

    【讨论】:

    • 如前所述,其中一个问题也存在于第三方组件中,我无法控制它们,因此无法按照您的建议进行条件语句。
    • [礼貌] 第三方组件旨在做他们所做的事情。除非所有者为您提供必要的受保护/公共方法和属性,否则您不能有条件地渲染它们的一部分。
    • 当内容缺失时,第 3 方组件可以检测到 null 并将其排除在外。但是,如果您将该组件包装成一个更大的组件,并且该内容作为 RenderFragment 从外部传递,则您无法检测到 null 并忽略传递“空”部分(不是 null)。例如。如果那是一个工具提示、错误框或类似的,你会要求组件给你一个空白框。
    猜你喜欢
    • 1970-01-01
    • 2022-01-06
    • 1970-01-01
    • 2018-09-13
    • 2019-02-18
    • 1970-01-01
    • 2018-12-20
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多