用ChildContent RenderFragments继承Blazor? [英] Blazor Inheritance with ChildContent RenderFragments?
问题描述
假设我们有一个基本组件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/编译器中的功能清楚地将代码的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
,这将使流向上返回到子级,然后调用其BuildRenderTree
,HasRendered
检查将确保避免无限循环,然后在返回父级完成之前呈现标记的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屋!