带有ChildContent RenderFragments的Blazor继承?

时间:2020-10-15 09:08:50

标签: blazor blazor-server-side

假设我们有一个基本组成部分ParentComponent.razor

<div id="ParentComponent">@ChildContent</div>

@code {
    [Parameter] public RenderFragment ChildContent {get;set;}
}

可以这样使用:

<ParentComponent>
    <div>content</div>
</ParentComponent>

哪个会渲染:

<div id="ParentComponent"><div>content</div></div>

但是请说我们希望ChildComponent.razor继承自ParentComponent.razor

@inherits ParentComponent

<div id="ChildComponent">@ChildContent</div>

@code {
    [Parameter] public RenderFragment ChildContent {get;set;}
}

是否可以通过ChildComponent填充ParentComponent的@ChildContent RenderFragment?

<ChildComponent>
    child content
</ChildComponent>

要产生这个:

<div id="ParentComponent">
    <div id="ChildComponent">child content</div>
</div>

不知道我是否遗漏了一些明显的东西,但是已经有一段时间搞不清了,并且无法在互联网上找到任何答案。

编辑-替代解决方案

我找到了另一种方法,该方法不依赖于直接使用覆盖BuildRenderTree方法,并允许您使用html / razor标记,尽管这确实意味着要四处走动。还不确定这是安全还是有效,但出于完整性考虑,请放在此处。

ParentElement.razor

@using Microsoft.AspNetCore.Components.Rendering;

@if (!HasRendered()) {
    SetRenderedStatus();
    <div id="ParentComponent">
        RenderChild(__builder);
    </div>
}

@code {
    protected bool _hasBaseRendered = false;

    protected bool HasRendered() {
        return _hasBaseRendered;
    }

    protected void SetRenderedStatus() {
         _hasBaseRendered = true;
    }

    protected virtual void RenderChild(RenderTreeBuilder __builder) { }
}

ChildElement.razor

@using Microsoft.AspNetCore.Components.Rendering
@inherits ParentElement

@if (HasRendered()) {
    <div id="ChildComponent">
         @ChildContent
    </div>
}
@{
    base.BuildRenderTree(__builder);
}

@code {
    [Parameter] public RenderFragment ChildContent { get; set; }

    protected override void RenderChild(RenderTreeBuilder __builder) {
        this.BuildRenderTree(__builder);
    }
}

如此简单的解释,IDE / Compiler中的功能清楚地将代码的razor / html标记部分编译为幕后的BuildRenderTree方法,这就是为什么您不能在{ {1}}组件。

以上代码可编译为:

.razor

ChildElement.razor

因此,当protected override void BuildRenderTree(RenderTreeBuilder __builder) { if (HasRendered()) { __builder.AddContent(0, " "); __builder.OpenElement(1, "div"); __builder.AddAttribute(2, "id", "ChildComponent"); __builder.AddMarkupContent(3, "\r\n "); __builder.AddContent(4, ChildContent); __builder.AddMarkupContent(5, "\r\n "); __builder.CloseElement(); __builder.AddMarkupContent(6, "\r\n"); } base.BuildRenderTree(__builder); } 为false时,ChildContent将被忽略,并直接在父类上调用HasRendered

base.BuildRenderTree

ParentElement.razor

它呈现父母标记,并且中途被定向到在孩子上被覆盖的protected override void BuildRenderTree(RenderTreeBuilder __builder) { if (!HasRendered()) { SetRenderedStatus(); __builder.AddContent(0, " "); __builder.OpenElement(1, "div"); __builder.AddAttribute(2, "id", "ParentComponent"); __builder.AddMarkupContent(3, "\r\n"); RenderChild(__builder); __builder.AddContent(4, " "); __builder.CloseElement(); __builder.AddMarkupContent(5, "\r\n"); } } ,这将流返回到孩子的某个级别,然后在其上调用其RenderChild,{ {1}}检查将确保避免无限循环,然后呈现标记的childs部分,然后再返回给父级以完成。

这可能是重构的,只是我当前的工作复制实验。

2 个答案:

答案 0 :(得分:1)

复制并测试...

ParentComponent.cs

left: 0

ChildComponent.cs

TextAlign.center

Index.razor

public partial class ParentComponent : ComponentBase
{
    [Parameter] public RenderFragment ChildContent { get; set; }

    protected override void BuildRenderTree(RenderTreeBuilder builder)
    {
        builder.OpenElement(0, "div");
        builder.AddAttribute(1, "id", "ParentComponent");
        builder.AddContent(2, ChildContent);
        builder.CloseElement();
        
        base.BuildRenderTree(builder);
    }
}

答案 1 :(得分:0)

我刚刚在5.0 rc2上对此进行了测试。

@inherits ParentComponent

<div id="ChildComponent">@ParentRenderFragment</div>

@code {

    RenderFragment ParentRenderFragment => builder =>
    {
        builder.OpenComponent<ParentComponent>(1);
        builder.AddAttribute(2, "ChildContent", this.ChildContent);
        // Additional inherited parameter's here
        builder.CloseComponent();
    };

}

产生了这个:

enter image description here

注意:

id是错误的,因为它们是作为renderfragment的一部分传递的。如果您无权编辑子组件,则可能需要对dom进行修复,因为您需要捕获属性或将id作为参数传递。

但是,这说明了如何将父母的原始照片呈现给孩子。