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

Blazor SSR中MudBlazor Dialog多次触发时抛出焦点无效错误

Blazor SSR中MudTable图片双击触发Dialog时的JS异常解决

问题分析

在Blazor Server Side Rendering项目中,使用MudTable展示图片,点击图片调用MudBlazor的DialogService打开原图弹窗时,单次点击正常,但在Dialog完成渲染前双击图片,控制台会抛出Microsoft.JSInterop.JSException: Unable to focus an invalid element异常。

该问题核心是短时间内重复调用DialogService.Show(),导致多个Dialog实例同时初始化,MudBlazor内部尝试聚焦Dialog元素时,DOM元素尚未就绪或被后续操作干扰,从而触发聚焦无效元素的错误。添加Task.Delay()能缓解是因为延迟给了第一个Dialog足够的初始化时间,避免重复创建冲突,但这只是临时 workaround。

根本解决方案

方案1:添加点击防抖(推荐)

在打开Dialog的方法中加入状态标记,阻止短时间内的重复调用:

@inject IDialogService DialogService

<!-- MudTable中的图片组件 -->
<MudImage Fluid="true" Style="max-height:100px" Src=@context.ImgSrc Class="cursor-pointer" @onclick=@(() => ShowImageDialog(context.ImgSrc))></MudImage>

@code {
    // 标记是否正在打开Dialog
    private bool _isDialogOpening;

    private async Task ShowImageDialog(string imageUrl)
    {
        // 如果正在打开,直接返回,阻止重复触发
        if (_isDialogOpening) return;
        
        _isDialogOpening = true;
        try
        {
            var parameters = new DialogParameters { ["ImageUrl"] = imageUrl };
            var options = new DialogOptions 
            { 
                MaxWidth = MaxWidth.ExtraLarge, 
                NoHeader = true, 
                FullWidth = false, 
                CloseButton = true, 
                CloseOnEscapeKey = true 
            };
            var dialog = DialogService.Show<Shared.ImageFull>("", parameters, options);
            
            // 可选:等待Dialog关闭后再重置标记(限制同时只能打开一个Dialog)
            await dialog.Result;
        }
        finally
        {
            // 无论成功失败,都重置标记
            _isDialogOpening = false;
        }
    }
}

方案2:检查已有Dialog实例

通过DialogService的已打开Dialog列表,检查是否存在相同的原图Dialog,避免重复创建:

private async Task ShowImageDialog(string imageUrl)
{
    // 检查是否已有展示该图片的Dialog
    var existingDialog = DialogService.GetDialogs().FirstOrDefault(d => 
        d.ComponentType == typeof(Shared.ImageFull) && 
        d.Parameters.ContainsKey("ImageUrl") && 
        d.Parameters["ImageUrl"].ToString() == imageUrl);
    
    if (existingDialog != null)
    {
        // 如果已有,将其前置或直接返回
        existingDialog.DialogReference.Show();
        return;
    }

    // 否则创建新Dialog
    var parameters = new DialogParameters { ["ImageUrl"] = imageUrl };
    var options = new DialogOptions { MaxWidth = MaxWidth.ExtraLarge, NoHeader = true, FullWidth = false, CloseButton = true, CloseOnEscapeKey = true };
    DialogService.Show<Shared.ImageFull>("", parameters, options);
}

方案说明

  • 方案1通过状态标记阻止重复触发,实现简单高效,从根源上避免重复创建Dialog导致的DOM冲突。
  • 方案2适合需要允许同时打开多个不同图片Dialog,但要避免重复打开同一张图的场景。

内容的提问来源于stack exchange,提问作者Chris Verros

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.21 10:43:22