聊天室会话列表与未读计数应采用 map+有序 id 列表分层建模,按事件驱动更新 unreadcount,通过就地修改而非全量替换保障响应性,并联动登录、进出房间等状态动态维护。

聊天室会话列表和未读消息计数属于典型的「跨会话共享状态」,需兼顾响应性、一致性与轻量更新。用 reactive 管理时,关键不是把所有数据塞进一个大对象,而是按语义分层建模,并配合细粒度更新逻辑。
会话列表结构要支持快速定位与状态同步
不要只存一个扁平数组,建议用 Map + 对象组合:
-
主结构用
Map<string sessionitem></string>:以GROUP${roomId}为 key(必须与 IM 会话 ID 一致),方便 O(1) 查找当前会话、切换会话或更新某一项 -
每项 SessionItem 包含基础字段:
id(即 GROUP+roomId)、name(房间名)、lastMessage、unreadCount、isMuted、updatedAt -
额外维护一个有序 id 列表(如
ref<string>([])</string>):用于控制左侧导航栏渲染顺序,避免每次排序开销
未读计数更新必须绑定消息收发生命周期
未读数不是独立变量,它依赖消息流向——谁发、谁收、是否已读、是否在当前会话。所以不能靠手动加减,而应由事件驱动:
- 收到新消息且 当前不在该会话页 → 对应
SessionItem.unreadCount++ - 用户点击进入某会话 → 立即调用 IM SDK 的
markMessagesAsRead,并重置其unreadCount = 0 - 主动发送消息后,若目标会话非当前页,不增加对方未读数(由对方侧逻辑处理),自己侧无需变更
- 撤回/删除消息时,需判断是否已读:若未读,
unreadCount--;若已读,不影响计数
响应式更新要避免全量替换,优先就地修改
Vue 的 reactive 对嵌套对象是深度响应的,但直接赋值整个 Map 或数组会丢失响应性。正确做法:
- 新增会话:用
sessionMap.set(id, newItem),不用sessionMap = new Map(...) - 更新未读数:直接改属性
sessionMap.get(id)!.unreadCount = newValue - 排序刷新:只更新
orderedIds.value = [...sessionMap.keys()].sort(...),不重建 Map - 删除会话:用
sessionMap.delete(id),再从orderedIds中过滤掉该 id
注意与登录/房间状态联动
会话列表不是静态缓存,它随用户身份和房间进出动态变化:
- 用户登录后,应拉取历史会话列表(含 unreadCount),初始化
reactive结构 - 加入新房间时,立即插入一条
GROUP${roomId}记录,默认unreadCount: 0 - 离开房间或被踢出时,从 Map 中移除对应项,并清空其本地消息缓存(避免残留)
- 登出时,可整体重置 Map 和 orderedIds,不必保留旧状态
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











