Blazor 全局通知服务通过创建 NotificationService 管理通知队列并触发 UI 更新,配合 NotificationItem 组件渲染,注册为 scoped 服务后在任意组件中注入调用 Show() 方法即可显示通知。

Blazor 实现全局通知服务,核心是创建一个可被任意组件注入、跨页面共享状态的 Service,并配合一个统一的 UI 组件(如 Toast 或 Banner)来渲染通知。关键在于状态管理 + 组件通信 + 生命周期控制。
1. 定义通知数据模型和通知服务
先定义一个轻量通知类,包含类型(Success/Info/Error/Warning)、内容、持续时间、是否自动关闭等字段:
public class Notification {public string Id { get;} = Guid.NewGuid().ToString(); public string Message {get; set;} = string.Empty; public NotificationType Type {get; set;} = NotificationType.Info; public int DurationMs {get; set;} = 5000; public bool AutoDismiss {get; set;} = true; } public enum NotificationType {Info, Success, Warning, Error}
然后创建 NotificationService,用 List<notification></notification> 管理队列,提供添加、移除、清空方法。注意用 INotifyPropertyChanged 或 Blazor 的 StateHasChanged() 机制触发 UI 更新——推荐用 EventCallback 或 Subject<notification></notification>(配合 Rx.NET)或更简单的方式:直接暴露一个 EventCallback 委托供 UI 订阅:
public class NotificationService {private readonly List<Notification> _notifications = new(); public event Action? OnNotificationsChanged; public IReadOnlyList<Notification> Notifications => _notifications.AsReadOnly(); public void Show(string message, NotificationType type = NotificationType.Info, int durationMs = 5000) {var notification = new Notification { Message = message, Type = type, DurationMs = durationMs}; _notifications.Add(notification); OnNotificationsChanged?.Invoke(); if (notification.AutoDismiss) {_ = Task.Delay(durationMs).ContinueWith(_ => { Dismiss(notification.Id); }); } } public void Dismiss(string id) {_notifications.RemoveAll(n => n.Id == id); OnNotificationsChanged?.Invoke();} public void Clear() { _notifications.Clear(); OnNotificationsChanged?.Invoke();} }
2. 注册服务并注入到根组件
在 Program.cs(.NET 6+)中注册为 scoped 服务:
builder.Services.AddScoped<NotificationService>();
在 App.razor 或 MainLayout.razor 顶部注入服务,并订阅变化:
@inject NotificationService NotificationService @if (NotificationService.Notifications.Any()) {<div class="notification-container"> @foreach (var notification in NotificationService.Notifications) {<NotificationItem Notification="@notification" OnDismiss="() => NotificationService.Dismiss(notification.Id)" /> } </div> } @code {private void HandleNotificationsChanged() => StateHasChanged(); protected override void OnInitialized() {NotificationService.OnNotificationsChanged += HandleNotificationsChanged;} public void Dispose() { NotificationService.OnNotificationsChanged -= HandleNotificationsChanged;} }
3. 创建可复用的通知 UI 组件(NotificationItem.razor)
封装单条通知的样式与交互,支持手动关闭、动画入场 / 离场(可用 CSS transition 或第三方库如 blazored-toast):
@using System.Text.RegularExpressions <div class="notification @GetCssClass()" @key="Notification.Id"> <span class="notification-icon">@GetIcon()</span> <span class="notification-message">@Notification.Message</span> <button class="notification-close" @onclick="() => OnDismiss.InvokeAsync()">✕</button> </div> @code {[Parameter] public Notification Notification {get; set;} = default!; [Parameter] public EventCallback OnDismiss {get; set;} private string GetCssClass() => $"notification-{Notification.Type.ToString().ToLower()}"; private string GetIcon() { return Notification.Type switch { NotificationType.Success => "✓", NotificationType.Error => "✗", NotificationType.Warning => "⚠", _ => "ℹ"}; } }
CSS 示例(加到 wwwroot/css/app.css 或组件内):
.notification-container {position: fixed; top: 1rem; right: 1rem; z-index: 1000; display: flex; flex-direction: column; gap: 0.5rem; max-width: 350px;} .notification {padding: 0.75rem 1rem; border-radius: 4px; box-shadow: 0 2px 8px rgba(0,0,0,0.15); display: flex; align-items: center; gap: 0.5rem; animation: slideInRight 0.3s ease-out; transition: opacity 0.3s, transform 0.3s; } .notification:not(:first-child) {margin-top: 0.25rem;} .notification-info {background: #e3f2fd; color: #1565c0;} .notification-success {background: #e8f5e9; color: #2e7d32;} .notification-warning {background: #fff8e1; color: #f57c00;} .notification-error {background: #ffebee; color: #c62828;} .notification-close {background: none; border: none; font-size: 1.2rem; cursor: pointer; margin-left: auto; color: inherit; opacity: 0.7;} .notification-close:hover {opacity: 1;} @keyframes slideInRight {from { transform: translateX(100%); opacity: 0; } to {transform: translateX(0); opacity: 1; } }
4. 在任意组件中使用通知
哪里需要就在哪里 @inject NotificationService,调用 Show() 即可:
@inject NotificationService NotificationService <button @onclick="ShowSuccess"> 显示成功通知 </button> @code {private void ShowSuccess() => NotificationService.Show(" 操作已成功!", NotificationType.Success); }
支持异步操作后通知:
private async Task SubmitForm() { try { await httpClient.PostAsJsonAsync("/api/save", model); NotificationService.Show(" 保存成功 ", NotificationType.Success); } catch {NotificationService.Show(" 保存失败,请重试 ", NotificationType.Error); } }
基本上就这些。不复杂但容易忽略的是:服务生命周期要匹配(scoped 最常用)、UI 订阅 / 取消订阅要配对、避免内存泄漏(尤其用委托事件时),以及通知叠加时的 z-index 和定位控制。进阶可加队列限流、点击跳转、自定义模板、声音提示等。






























