假设我们有一个基本组成部分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部分,然后再返回给父级以完成。
这可能是重构的,只是我当前的工作复制实验。
答案 0 :(得分:1)
复制并测试...
left: 0
TextAlign.center
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();
};
}
id是错误的,因为它们是作为renderfragment的一部分传递的。如果您无权编辑子组件,则可能需要对dom进行修复,因为您需要捕获属性或将id作为参数传递。
但是,这说明了如何将父母的原始照片呈现给孩子。