用ChildContent RenderFragments继承Blazor? [英] Blazor Inheritance with ChildContent RenderFragments?

查看:15
本文介绍了用ChildContent RenderFragments继承Blazor?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

假设我们有一个基本组件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的@ChildContentRenderFragment?

<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/编译器中的功能清楚地将代码的razor/html标记部分编译成幕后的BuildRenderTree方法,这就是为什么您不能在.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, "
        ");
        __builder.AddContent(4, ChildContent);
        __builder.AddMarkupContent(5, "
    ");
        __builder.CloseElement();
        __builder.AddMarkupContent(6, "
");          
    }
    base.BuildRenderTree(__builder);
}

因此,当HasRendered为False时,将忽略ChildContent,并被定向为调用父类上的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, "
");
        RenderChild(__builder);
        __builder.AddContent(4, "        ");
        __builder.CloseElement();
        __builder.AddMarkupContent(5, "
");
    }
}

它呈现父级标记,中途定向到在子级上被重写的RenderChild,这将使流向上返回到子级,然后调用其BuildRenderTreeHasRendered检查将确保避免无限循环,然后在返回父级完成之前呈现标记的Childs部分。

这可能是可以重构的,就是我目前的工作副本实验。

推荐答案

复制并测试...

ParentComponent.cs

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);
    }
}

ChildComponent.cs

public partial class ChildComponent : ParentComponent
{
    protected override void BuildRenderTree(RenderTreeBuilder builder)
    {
        builder.OpenComponent<ParentComponent>(0);
        builder.AddAttribute(1, "ChildContent", (RenderFragment)((builder2) => 
       {
            builder2.OpenElement(1, "div");
            builder2.AddAttribute(2, "id", "ChildComponent");
            builder2.AddContent(3, ChildContent);
            builder2.CloseElement();
        } ));

        builder.CloseComponent();
    
    }
}

索引.razor

@page "/"

<ChildComponent>child content</ChildComponent>

这篇关于用ChildContent RenderFragments继承Blazor?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆