You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.10 10:44:51