Vue 3 WebSocket 自定义 Hook:自动重连与心跳检测完整实现
本文介绍如何在Vue3中封装一个功能完善的WebSocket Hook,实现实时通信功能。该Hook支持自动连接、自动重连(可配置次数和间隔)、心跳检测、状态管理、消息发送及自动清理资源等核心功能。通过详细的代码实现展示了如何创建可复用的WebSocket工具,包括连接管理、错误处理和心跳机制。文章还提供了基本使用方法和在Composition API中的实践示例,并列举了可配置选项和注意事项。该
本文详细介绍如何在 Vue 3 中封装一个功能完善的 WebSocket Hook,支持自动重连、心跳检测等核心功能。
概述
在现代 Web 应用中,实时通信变得越来越重要。WebSocket 作为一种全双工通信协议,能够实现客户端与服务器之间的持久连接。本文将介绍如何在 Vue 3 中封装一个功能完善的 WebSocket Hook,支持自动重连、心跳检测等核心功能。
核心功能
-
自动连接 - 创建 Hook 时自动建立连接
-
自动重连 - 连接断开后自动尝试重新连接,可配置重试次数和间隔
-
心跳检测 - 定期发送心跳包保持连接活跃
-
状态管理 - 跟踪连接状态(未连接/连接中/已连接)
-
消息发送 - 提供统一的消息发送方法
-
自动清理 - 组件卸载时自动关闭连接和清理资源完整代码实现
完整代码实现
import { ref, onUnmounted } from "vue";
export default (url, options = {}) => {
// 默认配置
const {
reconnectLimit = 3, // 重连限制次 number | null = 无限重连
reconnectInterval = 3000, // 重连间隔 ms
heartbeatInterval = 30000, // 心跳间隔 ms
onOpen, // 连接成功时的回调函数
onError, // 连接出错时的回调函数
onMessage, // 收到消息时的回调函数
onClose, // 连接关闭时的回调函数
} = options;
let status = "disconnected"; // 'disconnected: 未连接' | 'connecting: 正在连接' | 'connected: 已连接'
let socket = null; // socket 对象
let reconnectCount = 0; // 重新连接次数
let reconnectTimer = null; // 重新连接计时器
let heartbeatTimer = null; // 心跳计时器
// 初始化 WebSocket
const initWebSocket = () => {
if (socket) socket.close();
status = "connecting";
socket = new WebSocket(url);
socket.onopen = (event) => {
status = "connected";
reconnectCount = 0;
startHeartbeat();
onOpen?.(event);
};
socket.onmessage = (event) => {
if (event.data === "pong" || event.data === "ping") return; // 忽略心跳响应
onMessage?.(event.data);
};
socket.onerror = (error) => {
onError?.(error);
handleDisconnect();
};
socket.onclose = (event) => {
onClose?.(event);
handleDisconnect();
};
};
// 处理断开连接
const handleDisconnect = () => {
status = "disconnected";
stopHeartbeat();
if (reconnectLimit === null || reconnectCount < reconnectLimit) {
reconnectCount++;
reconnectTimer = setTimeout(initWebSocket, reconnectInterval);
}
};
// 启动心跳
const startHeartbeat = () => {
stopHeartbeat();
heartbeatTimer = setInterval(() => {
if (status === "connected" && socket) {
socket.send("ping");
}
}, heartbeatInterval);
};
// 停止心跳
const stopHeartbeat = () => {
if (heartbeatTimer) {
clearInterval(heartbeatTimer);
heartbeatTimer = null;
}
};
// 连接 WebSocket
const connect = () => {
if (status !== "disconnected") return;
reconnectCount = 0;
initWebSocket();
};
// 断开 WebSocket
const disconnect = () => {
if (status !== "connected") return;
socket?.close(1000, "User disconnected");
};
// 发送消息
const send = (message) => {
if (status !== "connected" || !socket) return;
socket.send(
typeof message === "object" ? JSON.stringify(message) : message
);
};
// 组件卸载时清理
onUnmounted(() => {
disconnect();
if (reconnectTimer) clearTimeout(reconnectTimer);
stopHeartbeat();
});
// 自动连接
connect();
return {
connect,
disconnect,
send,
getStatus: () => status,
getReconnectCount: () => reconnectCount
};
};
使用方法
1.基本使用
import useSocket from "@/hooks/websocket";
// 在组件中使用
export default {
setup() {
const wsUrl = "wss://your-websocket-server.com";
const { send, disconnect, connect } = useSocket(wsUrl, {
onOpen: () => console.log("WebSocket 连接成功"),
onClose: () => console.log("WebSocket 断开连接"),
onError: (err) => console.log("WebSocket 连接错误", err),
onMessage: (data) => {
console.log("收到消息:", data);
// 处理收到的消息
},
});
// 发送消息
const sendMessage = () => {
send({ type: "message", content: "Hello WebSocket!" });
};
return {
sendMessage,
disconnect,
connect
};
}
};
2.在 Composition API 中的使用
import { ref, onMounted } from "vue";
import useSocket from "@/hooks/websocket";
export default {
setup() {
const messages = ref([]);
const wsUrl = "wss://your-websocket-server.com";
// 使用 WebSocket Hook
const { send } = useSocket(wsUrl, {
onOpen: () => {
console.log("WebSocket 连接成功");
// 连接成功后发送认证消息等
send({ type: "auth", token: "your-token" });
},
onClose: () => console.log("WebSocket 断开连接"),
onError: (err) => console.error("WebSocket 连接错误", err),
onMessage: (data) => {
try {
const message = JSON.parse(data);
messages.value.push(message);
} catch (e) {
console.error("消息解析错误:", e);
}
},
});
// 发送消息
const sendMessage = (content) => {
send({ type: "chat", content });
};
return {
messages,
sendMessage
};
}
};
配置选项
| 参数名 | 类型 | 默认值 | 描述 |
|---|---|---|---|
| reconnectLimit | number | 3 | 重连限制次数,设置为 null 表示无限重连 |
| reconnectInterval | number | 3000 | 重连间隔时间(毫秒) |
| heartbeatInterval | number | 30000 | 心跳间隔时间(毫秒) |
| onOpen | function | null | 连接成功时的回调函数 |
| onError | function | null | 连接出错时的回调函数 |
| onMessage | function | null | 收到消息时的回调函数 |
| onClose | function | null | 连接关闭时的回调函数 |
注意事项
-
心跳协议:确保你的 WebSocket 服务器能正确处理 "ping" 消息并可能返回 "pong" 响应
-
重连策略:根据实际需求调整重连次数和间隔
-
错误处理:合理处理连接错误和消息解析错误
-
资源清理:组件卸载时确保正确关闭连接和清理定时器
总结
本文介绍的 WebSocket Hook 提供了一个强大且灵活的解决方案,用于在 Vue 3 应用中管理 WebSocket 连接。通过自动重连、心跳检测等功能的封装,大大简化了 WebSocket 的使用复杂度,提高了开发效率和应用稳定性。
你可以根据实际项目需求进一步扩展这个 Hook,比如添加消息队列、连接状态变更事件、重连策略自定义等功能。
💰【我的自研工具推荐】轻松网购返利,技术人的省钱助手
✅ 自用省钱,分享有奖
支持主流电商平台 | 返利透明可提现
👇 微信扫码,立即体验

说明:本工具为我个人独立开发,若您有技术合作或使用疑问,欢迎在博客私信交流。
火山引擎开发者社区是火山引擎打造的AI技术生态平台,聚焦Agent与大模型开发,提供豆包系列模型(图像/视频/视觉)、智能分析与会话工具,并配套评测集、动手实验室及行业案例库。社区通过技术沙龙、挑战赛等活动促进开发者成长,新用户可领50万Tokens权益,助力构建智能应用。
更多推荐

所有评论(0)