vue 的 reactive 仅提供响应式能力,不直接管理通知队列或已读状态;需结合业务逻辑、计算属性、封装操作函数(如 markasread)、持久化(localstorage)及跨组件共享机制(pinia/store)来完整实现通知系统。

Vue 的 reactive 本身不直接管理通知消息队列或已读状态,它只是提供响应式数据能力。真正实现通知系统(如队列、未读数、已读标记)需要结合业务逻辑、状态结构设计和副作用协调(比如 nextTick 或事件驱动),而非 reactive 单独完成。
下面从实际落地角度说明如何用 reactive 配合其他机制来管理系统通知:
通知数据结构需支持队列与状态标记
用 reactive 定义一个能反映真实业务状态的通知对象,例如:
const notifications = reactive({
list: [
{ id: 1, title: '系统更新完成', content: 'v2.3.0 已上线', read: false, time: '2026-07-28T10:22:00' },
{ id: 2, title: '审批待处理', content: '请审核采购单 #A7890', read: false, time: '2026-07-28T09:15:00' },
],
unreadCount: 2,
});
关键点:
-
list是响应式数组,增删改都会触发视图更新 -
read字段标识已读/未读,修改它会自动更新对应 UI(如 badge 消失、条目变灰) -
unreadCount不应手动维护,而应通过计算属性或同步逻辑保持一致性
保证未读数与列表状态严格同步
避免手动 ++/-- 导致错位,推荐用计算方式或封装操作函数:
// ✅ 推荐:封装 markAsRead 方法,自动更新 unreadCount
const markAsRead = (id) => {
const item = notifications.list.find(n => n.id === id);
if (item && !item.read) {
item.read = true;
notifications.unreadCount--;
}
};
// ✅ 或更健壮:每次修改后重算
const refreshUnreadCount = () => {
notifications.unreadCount = notifications.list.filter(n => !n.read).length;
};
// 调用后立即刷新(尤其在批量操作时)
markAsRead(1);
refreshUnreadCount();
消息入队需保证响应式更新及时性
新消息到来时(如 WebSocket 推送),直接 push 到 list 即可触发更新:
const addNotification = (msg) => {
notifications.list.push({
id: Date.now(),
title: msg.title,
content: msg.content,
read: false,
time: new Date().toISOString(),
});
notifications.unreadCount++; // 或调用 refreshUnreadCount()
};
注意:若消息来自异步源(如 fetch 或 onmessage),确保在主线程中执行 push,否则可能绕过响应式系统。
已读状态持久化与跨组件共享
reactive 仅限当前实例作用域。如需全局通知状态(如菜单 badge 和通知弹窗共用同一未读数),应:
- 将
notifications提升为组合式函数(composable)或 Pinia store - 使用
readonly()包裹对外暴露只读副本,防止误改 - 在 store 中集成本地存储(如
localStorage)同步已读状态:
// 初始化时从 localStorage 恢复
const loadFromStorage = () => {
const saved = localStorage.getItem('notifications');
if (saved) {
const parsed = JSON.parse(saved);
notifications.list = parsed.list || [];
notifications.unreadCount = parsed.unreadCount || 0;
}
};
// 发生变更时保存
watch(() => notifications, () => {
localStorage.setItem('notifications', JSON.stringify({
list: notifications.list,
unreadCount: notifications.unreadCount,
}));
}, { deep: true });
清除已读消息时注意响应式边界
不要用 list.length = 0(会破坏响应式追踪),应使用 splice(0) 或 replace:
const clearRead = () => {
const readIds = notifications.list.filter(n => n.read).map(n => n.id);
notifications.list = notifications.list.filter(n => !readIds.includes(n.id));
refreshUnreadCount();
};
这样既保持响应式,又避免意外丢失 reactivity。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!










