我想测试是否可以动态创建Blazor组件。
我找不到任何方法来实现这一点。我尝试过在此链接中找到的一些动态内容,但是没有得到任何结果。
我想测试是否可以动态创建Blazor组件。
我找不到任何方法来实现这一点。我尝试过在此链接中找到的一些动态内容,但是没有得到任何结果。
@if (_showCounter)
{
<MyCounterComponent Count="@_count" />
}
@code {
bool _showCounter = true;
int _count;
}
对于重复的数据集,例如项目列表,您可以利用Blazor的数据绑定功能。
以显示销售订单并为每个销售订单行设置一个子组件的页面/组件为例。您可能在razor页面上有以下代码:
@foreach (var salesOrderLine in _salesOrder.salesOrderlines)
{
<SalesOrderLine SOLine=@salesOrderLine />
};
_salesOrder
模型/视图模型中。按钮点击通常会触发重新呈现,因此页面应自动显示额外的SalesOrderLine
组件(如果没有,则可以使用this.StateHasChanged();
告诉它事情已经改变并引起重新呈现)。
<ul>
@foreach (fruit in fruits)
{
switch(fruit)
{
case PearComponent p:
<PearComponent ParameterOfSomeSort="p"></PearComponent>
<li>Or render pears like this, if you want the li in it</li>
break;
case AppleComponent a:
<AppleComponent></AppleComponent>
break;
case BananaComponent b:
<BananaComponent></BananaComponent>
break;
case RaspberryComponent r:
<RaspberryComponent></RaspberryComponent>
break;
}
}
</ul>
有些情况无法使用上述的Razor方法来处理。在这些情况下,RenderFragment
提供了另一种动态渲染页面部分的方式。
如果您有一个真正的多态列表(例如,一个实现相同接口或从相同类继承的对象列表),则可以使用此类型的方法来自此GitHub帖子:
@page "/"
@foreach (CounterParent counter in components)
{
RenderFragment renderFragment = (builder) => { builder.OpenComponent(0, counter.GetType()); builder.CloseComponent(); };
<div>
<div>Before the component</div>
@renderFragment
<div>Afterthe component</div>
</div>
}
@code
{
List<CounterParent> components = new List<CounterParent>() { new CounterParent(), new CounterChild() };
}
Blazor团队正在考虑改进如何处理多态列表:
mkArtakMSFT于2019年10月1日发表评论感谢您与我们联系,@Joebeazelman。使用您拥有的转换方法将是我们的建议。我们将考虑在未来在这个领域做得更好。
这里的关键点(对于来自MVC背景的人)是没有必要尝试手动将新HTML注入DOM,或者以MVC方式动态加载部分视图,Blazor会为您完成。
尽管MVC和Blazor的Razor页面语法相似,但Blazor模型在概念上更接近于React而不是MVC,理解背景中类似于阴影DOM的内容非常重要。
RenderFragment
。然而,对于外部插件的多态渲染场景,RenderFragment
绝对是一个极好的用途。顺便说一下,Blazor团队正在努力改进多态处理,请参见我的答案中的github链接。 - tomRedox对于版本0.2,这是Steve Sanderson的答案:
我们将来会实现更好的API来构建RenderFragments,但是目前你可以
@CreateDynamicComponent(); @functions { RenderFragment CreateDynamicComponent() => builder => { builder.OpenComponent(0, typeof(SurveyPrompt)); builder.AddAttribute(1, "Title", "Some title"); builder.CloseComponent(); }; }
这些是非常低级的API(甚至没有文档记录),因此我们希望现在不需要太多人这样做。稍后会推出更高级别的API。
来源在此处
<DynamicComponent>
使所有这些相对轻松地实现。这是.NET 6的核心新增功能之一,该版本将于2021年11月正式发布。BuildRenderTree
来完成类似的操作,但通常不建议这样做,因为可能会出现错误。 (Microsoft文档)public class CustomLabel: ComponentBase
{
[Parameter] public string Id { get; set; }
[Parameter] public string? Label { get; set; }
protected override void BuildRenderTree(RenderTreeBuilder builder)
{
if (!string.IsNullOrEmpty(Label))
{
builder.OpenElement(1, "label");
builder.AddAttribute(2, "for", Id);
builder.AddAttribute(3, "class", "custom-css-classes-here");
builder.AddContent(4, Label);
builder.CloseElement();
}
}
// another example: maybe you would have an "IsRequired" flag
// that would add an "*" after the label if set to true
}