Blazor应用浏览器最小化时如何显示SignalR任务栏通知
问题本质
你当前使用的SfToast是Blazor页面内渲染的UI组件,仅能在浏览器视口范围内展示。当浏览器最小化、标签页失焦切到后台时,页面内组件无法突破浏览器沙箱触达系统层面的通知栏,必须配合浏览器原生的Web Notifications API才能实现系统级弹窗提醒。
具体实现步骤
- 第一步:封装JS交互方法
在项目wwwroot目录下的JS文件中(没有就新建一个,记得在_Host.cshtml或index.html中引用)添加通知权限请求、系统通知弹出的逻辑:
// 请求桌面通知权限 window.requestNotifyPermission = async function () { if (!("Notification" in window)) return false; const res = await Notification.requestPermission(); return res === "granted"; } // 触发系统通知 window.showDesktopToast = function (title, content, icon, jumpPath) { // 无权限或页面当前处于激活状态时,不弹系统通知,走原有页内Toast逻辑 if (Notification.permission !== "granted" || document.visibilityState === "visible") return; const notify = new Notification(title, { body: content, icon: icon, tag: "app-notify", // 同tag通知自动覆盖,避免重复堆叠 renotify: true }); // 点击通知自动切回应用窗口,可跳转至对应通知详情页 notify.onclick = () => { window.focus(); if (jumpPath) window.location.href = jumpPath; notify.close(); }; // 和原有页内Toast超时时间保持一致自动关闭 setTimeout(() => notify.close(), 5000); }
- 第二步:改造Blazor端逻辑
注入IJSRuntime用于JS互操作,调整SignalR消息接收逻辑,在页面后台时触发系统通知,同时补充你原有代码遗漏的Hub连接启动逻辑:
[Inject] protected IJSRuntime JSRuntime { get; set; } private HubConnection bpmHubConnection; private bool _desktopNotifyEnabled = false; protected async override Task OnInitializedAsync() { bpmHubConnection = new HubConnectionBuilder() .WithUrl(ONEERP.Web.Models.SessionManager.BpmApiBaseAddress + "hubs/BPMBroadCastHub") .Build(); bpmHubConnection.On<int, int, string, string>("SendNotification", async (userGroupID, userID, name, message) => { if (SessionManager.UserID == userID) { CallLoadNotification(); // 后台状态下触发系统通知 if (_desktopNotifyEnabled) { await JSRuntime.InvokeVoidAsync("showDesktopToast", "新通知提醒", message, "/images/notify-icon.png", // 替换为你自己的通知图标路径 "/notification/list"); // 替换为点击通知后要跳转的页面路径 } StateHasChanged(); } }); // 原有代码遗漏了Hub连接启动,必须加上 await bpmHubConnection.StartAsync(); }
- 第三步:添加用户授权入口
浏览器安全规则限制,通知权限必须由用户主动点击等交互行为触发申请,不能页面加载时自动请求(会被直接拦截)。在razor页面中添加授权按钮即可:
@* 未授权时显示开启按钮 *@ @if (!_desktopNotifyEnabled) { <button class="btn btn-sm text-muted" @onclick=OpenDesktopNotify> 开启桌面通知 </button> } @* 原有Toast组件保留,页面激活时正常显示 *@ <SfToast ID="toastNotification" ShowCloseButton="true" @ref="ToastNotificationObj" Title="Notification" Content="@ToastNotificationContent" CssClass="@ToastNotificationStyle" Timeout=@ConstantClass.ToastTimeout Icon="e-meeting"> <ToastPosition X="Right" Y="Bottom"></ToastPosition> </SfToast> @code { private async Task OpenDesktopNotify() { _desktopNotifyEnabled = await JSRuntime.InvokeAsync<bool>("requestNotifyPermission"); StateHasChanged(); } }
注意事项
- Web Notifications API仅在HTTPS环境下生效(本地localhost调试不受限制)
- 系统通知的样式由操作系统决定,无法自定义成和Syncfusion页内Toast完全一致的外观
- 如果需要更严格的后台存活能力,可以搭配Service Worker做离线通知,但普通业务场景下上述实现已经满足最小化/切后台时的提醒需求
- 可以额外监听
document的visibilitychange事件,实现更细粒度的弹窗策略,比如切后台超过30秒收到消息再弹系统通知,避免用户短暂切标签就被打扰
内容的提问来源于stack exchange,提问作者Muhammed Ismail
相关产品推荐
相关产品推荐

