用 watcheffect 实现 websocket 实时通知的核心是将连接状态、消息列表等封装为响应式 ref,通过监听登录态与页面可见性等信号自动触发连接、订阅、更新与清理,并在组件卸载或条件失效时安全断开并重连。

用 watchEffect 实现 WebSocket 实时通知,核心是让响应式数据变化自动触发连接管理与消息处理,而不是手动监听或轮询。关键在于:把 WebSocket 实例和接收的消息状态纳入 Vue 响应式系统,并用 watchEffect 统一协调「连接 → 订阅 → 更新 → 清理」生命周期。
将 WebSocket 状态封装为响应式引用
不能直接 watchEffect 一个原生 WebSocket 对象(它不是响应式),但可以封装它的关键状态:
- 用
ref管理连接状态(connected、error)和收到的通知列表(notifications) - 用
ref存储 WebSocket 实例本身(便于后续关闭),但注意:仅存储,不直接依赖它触发副作用 - 避免在
watchEffect内重复创建连接——需配合清理函数和连接条件判断
在 watchEffect 中声明式管理连接与订阅
watchEffect 的优势是自动追踪依赖并响应变化。可让它监听「是否需要连接」的信号(如用户登录态、页面可见性、通知开关):
WebSocket 8.18.2 是该协议规范的一个重要迭代版本,主要优化了连接稳定性与数据传输效率。它通过全双工通信机制,允许客户端与服务器在单一长连接上实时交换数据,大幅降低传统 HTTP 轮询的开销。该版本增强了心跳保活、自动重连及二进制帧传输能力,适用于即时通讯、在线游戏及金融行情推送等低延迟场景,为开发者提供更可靠的实时网络交互基础。
- 当
user.isLoggedIn.value && isPageVisible.value变为 true,自动建立连接并发送订阅消息(如{"type":"subscribe","channel":"notify"}) - 当任一条件变为 false,执行清理:发送退订、调用
ws.close()、重置状态 - 在回调中直接
ws.onmessage处理通知,推入notifications.value—— 触发视图更新
安全处理重连与重复订阅
WebSocket 断线很常见,但 watchEffect 不会自动重试。需主动设计容错逻辑:
- 在
onerror和onclose中设置connected.value = false,触发watchEffect重新评估(若条件仍满足,会再次尝试连接) - 用
setTimeout加延迟重连,避免雪崩;同时限制最大重试次数(用额外 ref 计数) - 发送订阅前检查
ws.readyState === WebSocket.OPEN,防止向正在关闭或未打开的连接发消息 - 服务端支持幂等订阅(重复订阅无副作用),前端发送订阅时附带唯一 client-id,便于服务端去重
组件卸载时自动清理连接
watchEffect 返回的清除函数会在副作用失效时调用(如组件 unmount),这是释放资源的关键时机:
- 在
watchEffect回调开头定义清理逻辑:if (ws.value) { ws.value.close(); ws.value = null; } - 确保
onmessage、onerror等事件监听器不造成内存泄漏——它们会随 WebSocket 实例销毁自然失效,但若用了箭头函数闭包持有组件作用域变量,需留意 - 如使用 Pinia store 管理全局通知,应在 store
onUnmounted或beforeUnmount钩子中显式调用断开方法,而非只依赖组件内watchEffect的清理
不复杂但容易忽略:watchEffect 的响应性依赖于内部读取的响应式属性。只要你在回调里真正用到了 user.isLoggedIn、isPageVisible 这些 ref,它就会自动联动。不需要手动调用 stop 或 watch 选项,Vue 会帮你搞定。










