使用GUID作为ID的Razor模态组件点击触发异常问题求助
问题:使用GUID作为ID的Razor模态框触发时出现找不到元素的错误
我开发了一个以GUID生成ID的Razor模态组件,点击按钮触发模态框时出现了如下错误。已确认模态框ID与按钮的data-bs-target值完全一致,但将ID设为静态值或页面生成大量元素时,错误会消失。

相关代码
首页代码
<div class="row alignToEnd "> <button class="roundButton " data-bs-toggle="modal" data-bs-target="#@modalPickerDevice.ID"><i class="fas fa-plus"></i></button> </div> <ModalPickerDevice @ref="modalPickerDevice"/> @code{ protected ModalPickerDevice modalPickerDevice = new(); }
Razor组件代码
<div class="modal fade " id="@ID" aria-hidden="true" aria-labelledby="exampleModalLabel" tabindex="-1" style="overflow-x: auto;"> <div class="modal-dialog"> <div class="modal-content "> <div class="modal-header"> <h5 class="modal-title"></h5> <button type="button" class="btn-close py-0" data-bs-dismiss="modal" aria-label="Close"></button> </div> <div class="modal-body"> </div> </div> </div> </div> @code{ public string ID { get; private set; } = $"ModalPickerDevice{Guid.NewGuid()}"; }
问题原因
核心问题是Blazor组件的生命周期管理冲突:
你手动通过new()创建了ModalPickerDevice实例,此时该实例的ID已经生成,但Blazor框架在渲染组件时,会自动创建一个全新的组件实例(手动创建的实例并不会被框架用于渲染)。这就导致按钮绑定的ID是手动实例的ID,而页面上实际渲染的模态框是框架生成的新实例的ID,两者不匹配,Bootstrap自然找不到对应的模态框元素。
至于静态ID或页面元素多的时候错误消失:静态ID不管实例怎么变都一致,所以不会有匹配问题;页面元素多的时候渲染延迟巧合让两次ID生成的时机重合,但这是不可靠的偶然情况。
解决方案
方案1:让Blazor框架管理组件引用(推荐)
不要手动new组件实例,通过OnAfterRenderAsync获取框架渲染的组件引用,再刷新UI同步ID:
<div class="row alignToEnd "> <button class="roundButton " data-bs-toggle="modal" data-bs-target="#@(modalPickerDevice?.ID ?? string.Empty)"><i class="fas fa-plus"></i></button> </div> <ModalPickerDevice @ref="modalPickerDevice"/> @code{ protected ModalPickerDevice modalPickerDevice; // 仅声明,不手动实例化 protected override async Task OnAfterRenderAsync(bool firstRender) { if (firstRender) { StateHasChanged(); // 获取引用后刷新UI,让按钮的target更新为正确ID } } }
方案2:外部传入ID,统一控制ID生成
修改组件允许外部传入ID,由父组件生成并传递,确保ID唯一且一致:
Razor组件修改
<div class="modal fade " id="@ID" aria-hidden="true" aria-labelledby="exampleModalLabel" tabindex="-1" style="overflow-x: auto;"> <!-- 其余内容不变 --> </div> @code{ [Parameter] public string ID { get; set; } = $"ModalPickerDevice{Guid.NewGuid()}"; }
首页代码修改
<div class="row alignToEnd "> <button class="roundButton " data-bs-toggle="modal" data-bs-target="#@modalId"><i class="fas fa-plus"></i></button> </div> <ModalPickerDevice ID="@modalId"/> @code{ private string modalId = $"ModalPickerDevice{Guid.NewGuid()}"; }
方案3:用JS手动触发模态框,避开ID匹配
通过Blazor的JS互操作手动调用Bootstrap的模态框方法,不需要依赖data-bs-target:
<div class="row alignToEnd "> <button class="roundButton " @onclick="OpenModal"><i class="fas fa-plus"></i></button> </div> <ModalPickerDevice @ref="modalPickerDevice"/> @code{ [Inject] private IJSRuntime JS { get; set; } protected ModalPickerDevice modalPickerDevice; private async Task OpenModal() { var modalElement = await JS.InvokeAsync<IJSObjectReference>("bootstrap.Modal.getOrCreateInstance", $"#{modalPickerDevice.ID}"); await modalElement.InvokeVoidAsync("show"); } }
内容的提问来源于stack exchange,提问作者Dazzyl
相关产品推荐
相关产品推荐

