如何在Blazor的Razor组件中引用其他Razor文件内容?
Blazor迭代列表时加载对应派生组件内容
早上好!
我谷歌搜了一整天都没找到结果(可能关键词不对),想知道有没有办法实现这个需求,或者最优方案是什么。
项目简化结构
- ItemCollection.razor
- ItemCollection.razor.cs
- Element.razor
- Element.razor.cs
- Element
- Item.razor
- Item.razor.cs
- Item.razor
现有组件代码
Element.razor
@namespace myns @inherit ComponentBase <style> .element { height: @this.Height; width: @this.Width; } </style>
Element.razor.cs
namespace myns; public partial class Element : ComponentBase { public string ID { get; set; } public string Height { get; set; } public string Width { get; set; } }
Item.razor
@namespace myns @inherit Element <style> .item { background-color: aqua; } </style>
Item.razor.cs
namespace myns; public partial class Item : Element { // 修正语法错误:移除多余return public virtual string Class => "item"; }
DerivedItem1.razor
@namespace myns @inherit Item <style> .item { background-color: black; } </style> <!-- 修正Blazor点击事件写法:使用@onclick而非原生onclick --> <div id="@base.ID" class="element @this.Class" @onclick="(e) => OnClick(this, e)"></div>
DerivedItem1.razor.cs
namespace myns; public partial class DerivedItem1 : Item { public override string Class => base.Class + " derived1"; // 补充点击方法定义 private void OnClick(object sender, EventArgs e) { // 自定义点击逻辑 } }
DerivedItem2.razor
@namespace myns @inherit Item <style> .item { background-color: red; } </style> <div id="@base.ID" class="element @this.Class" @onclick="(e) => OnClick(this, e)"></div>
DerivedItem2.razor.cs
namespace myns; public partial class DerivedItem2 : Item { public override string Class => base.Class + " derived2"; private void OnClick(object sender, EventArgs e) { // 自定义点击逻辑 } }
Collection.razor
namespace myns; @inherit ComponentBase @foreach (var item in this.Items) { @* 此处需根据item的派生类加载对应组件内容 *@ }
Collection.razor.cs
namespace myns; public partial class Collection<T> : ComponentBase { public List<T> Items { get; set; } }
Root.razor
namespace myns; @inherit ComponentBase <!-- 引用Collection组件 --> <Collection Items="@Items" />
Root.razor.cs
namespace myns; public partial class Root : ComponentBase { public Collection<Item> Items { get; set; } = new(); protected override void OnInitialized() { // 示例数据初始化 Items.Items.Add(new DerivedItem1 { ID = "item1", Height = "100px", Width = "100px" }); Items.Items.Add(new DerivedItem2 { ID = "item2", Height = "100px", Width = "100px" }); } }
实现方案
方案1:类型匹配渲染(适合已知派生类型)
直接在Collection组件中通过类型判断渲染对应派生组件,逻辑直观:
修改Collection.razor:
@namespace myns; @inherit ComponentBase @foreach (var item in this.Items) { if (item is DerivedItem1 derived1) { <DerivedItem1 ID="@derived1.ID" Height="@derived1.Height" Width="@derived1.Width" /> } else if (item is DerivedItem2 derived2) { <DerivedItem2 ID="@derived2.ID" Height="@derived2.Height" Width="@derived2.Width" /> } // 新增派生类型时,在此添加对应判断分支 }
方案2:基类定义RenderFragment(推荐,低耦合)
在Item基类中抽象渲染逻辑,让每个派生组件自行实现UI:
- 修改Item.razor.cs,添加抽象渲染片段:
namespace myns; public partial class Item : Element { public virtual string Class => "item"; // 抽象渲染逻辑,由派生类实现 public abstract RenderFragment RenderContent { get; } }
- 在DerivedItem1.razor.cs中实现RenderContent:
namespace myns; public partial class DerivedItem1 : Item { public override string Class => base.Class + " derived1"; public override RenderFragment RenderContent => builder => { builder.OpenElement(0, "div"); builder.AddAttribute(1, "id", base.ID); builder.AddAttribute(2, "class", $"element {this.Class}"); builder.AddAttribute(3, "onclick", EventCallback.Factory.Create<MouseEventArgs>(this, () => OnClick(this, EventArgs.Empty))); builder.CloseElement(); }; private void OnClick(object sender, EventArgs e) { // 自定义点击逻辑 } }
同理修改DerivedItem2.razor.cs实现自身RenderContent。
修改Collection.razor调用渲染片段:
@namespace myns; @inherit ComponentBase @foreach (var item in this.Items) { @item.RenderContent }
方案3:动态组件渲染(适合未知/动态派生类型)
使用Blazor的DynamicComponent自动匹配类型渲染组件,扩展性最强:
修改Collection.razor:
@namespace myns; @inherit ComponentBase @foreach (var item in this.Items) { <DynamicComponent Type="@item.GetType()" Parameters='new Dictionary<string, object> { { nameof(Element.ID), item.ID }, { nameof(Element.Height), item.Height }, { nameof(Element.Width), item.Width } }' /> }
新增派生类时无需修改Collection组件,自动适配渲染。
内容的提问来源于stack exchange,提问作者Ziemas Y.
相关产品推荐
相关产品推荐

