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
相关产品推荐
相关产品推荐

