Blazor从组件列表渲染动态元素无显示问题排查
Blazor组件未渲染问题排查
问题概述
在Blazor项目中,尝试通过foreach循环渲染DocumentUploader组件,初始化时向列表添加了组件实例,但页面无任何内容显示,也未抛出错误。
相关代码片段
页面Razor代码
@foreach (var documentUploader in documentUploaderElements) { <documentUploader /> }
页面初始化代码
protected override void OnInitialized() { var doc = new QT_Tagger.Shared.Details.DocumentUploader(); documentUploaderElements.Add(doc); StateHasChanged(); base.OnInitialized(); }
列表定义
private List<QT_Tagger.Shared.Details.DocumentUploader> documentUploaderElements = new List<Shared.Details.DocumentUploader>();
DocumentUploader组件完整代码
@inject IJSRuntime JsRuntime @inject NavigationManager NavManager <div style="margin-top: 10px; width: 80%" > <strong style="margin-top: 20px">Dokumenten-Titel*</strong> <p>Zur Anzeige auf der Artikelseite</p> <input @bind="Title" style="margin-top: 10px;" type="text" maxlength="80" placeholder="Titel: z.B: Original Rechung 01.01.2020"> <div class="form-group" style="margin-top: 10px; margin-bottom: 10px"> <strong class="headlines_options">Art des Dokuments</strong> <select id="selectedOption" style="margin-top: 10px; color: black; font-size: 13px; max-width: 80%" class="form-control" @bind="TypeOfResell"> <option selected style="color: black; font-size: 13px" value="@DocumentTypes.Rechnung"><strong>Rechnung</strong></option> <option style="color: black; font-size: 13px" value="@DocumentTypes.Garantie"><strong>Garantie</strong></option> <option style="color: black; font-size: 13px" value="@DocumentTypes.Andere"><strong>Andere</strong></option> </select> </div> <InputFile OnChange="@SingleUpload" class="custom-input-file" /> </div> @code { private string Title = ""; private string TypeOfResell = DocumentTypes.Rechnung.ToString(); private async Task SingleUpload(InputFileChangeEventArgs e) { MemoryStream ms = new MemoryStream(); await e.File.OpenReadStream().CopyToAsync(ms); var bytes = ms.ToArray(); //do something with bytes } protected override void OnInitialized() { base.OnInitialized(); } enum DocumentTypes { Rechnung, Garantie, Andere } }
错误原因
- 组件实例管理错误:Blazor组件的实例由框架负责创建和管理,手动
new组件实例并添加到列表的方式完全无效,框架不会识别这些手动创建的实例,也不会将其渲染到页面。 - 组件标签命名不规范:Blazor组件标签需要遵循HTML的kebab-case命名规则,PascalCase的组件名
DocumentUploader应转换为<document-uploader />(也可直接使用<DocumentUploader />,但kebab-case更符合HTML规范),原代码中的<documentUploader />不符合命名规范,可能导致框架无法识别组件。
解决方案
方案1:仅控制组件渲染数量(无数据绑定需求)
如果只是需要渲染固定数量的DocumentUploader组件,无需存储组件实例,直接用计数变量控制循环即可:
- 修改列表定义为计数变量:
private int uploaderCount = 0;
- 初始化时设置计数:
protected override void OnInitialized() { uploaderCount = 1; // 需要渲染的组件数量 base.OnInitialized(); }
- 修改Razor循环代码:
@for (int i = 0; i < uploaderCount; i++) { <document-uploader /> }
方案2:绑定组件数据(有数据交互需求)
如果需要为每个组件传递或管理数据,应创建数据模型而非存储组件实例:
- 创建组件对应的数据模型:
public class DocumentUploaderModel { public string Title { get; set; } = ""; public string TypeOfResell { get; set; } = "Rechnung"; }
- 修改列表定义为数据模型列表:
private List<DocumentUploaderModel> uploaderModels = new();
- 初始化时添加数据模型:
protected override void OnInitialized() { uploaderModels.Add(new DocumentUploaderModel()); base.OnInitialized(); }
- 修改
DocumentUploader组件,添加参数接收数据模型:
@inject IJSRuntime JsRuntime @inject NavigationManager NavManager <div style="margin-top: 10px; width: 80%" > <strong style="margin-top: 20px">Dokumenten-Titel*</strong> <p>Zur Anzeige auf der Artikelseite</p> <input @bind="Model.Title" style="margin-top: 10px;" type="text" maxlength="80" placeholder="Titel: z.B: Original Rechung 01.01.2020"> <div class="form-group" style="margin-top: 10px; margin-bottom: 10px"> <strong class="headlines_options">Art des Dokuments</strong> <select id="selectedOption" style="margin-top: 10px; color: black; font-size: 13px; max-width: 80%" class="form-control" @bind="Model.TypeOfResell"> <option selected style="color: black; font-size: 13px" value="@DocumentTypes.Rechnung"><strong>Rechnung</strong></option> <option style="color: black; font-size: 13px" value="@DocumentTypes.Garantie"><strong>Garantie</strong></option> <option style="color: black; font-size: 13px" value="@DocumentTypes.Andere"><strong>Andere</strong></option> </select> </div> <InputFile OnChange="@SingleUpload" class="custom-input-file" /> </div> @code { [Parameter] public DocumentUploaderModel Model { get; set; } = new(); private async Task SingleUpload(InputFileChangeEventArgs e) { MemoryStream ms = new MemoryStream(); await e.File.OpenReadStream().CopyToAsync(ms); var bytes = ms.ToArray(); //do something with bytes } enum DocumentTypes { Rechnung, Garantie, Andere } }
- 修改页面Razor循环代码,传递数据模型:
@foreach (var model in uploaderModels) { <document-uploader Model="model" /> }
额外说明
- 无需在
OnInitialized中手动调用StateHasChanged(),框架会在初始化完成后自动触发组件渲染。 - Blazor组件的渲染完全由框架控制,开发者只需通过Razor标签声明组件,并通过参数传递数据,无需手动管理组件实例。
内容的提问来源于stack exchange,提问作者innom
相关产品推荐
相关产品推荐

