const { status, data, send, close, open } = useWebSocket(server.value, { autoReconnect: true, heartbeat: true })
时间: 2025-07-22 13:38:11 浏览: 1
<think>我们使用 VueUse 的 useWebSocket 组合式函数来管理 WebSocket 连接。根据提供的代码片段,它设置了 autoReconnect 和 heartbeat 选项。
现在,我们将详细解释这两个选项的作用,并提供一个完整的示例,展示如何在实际组件中使用 useWebSocket 并处理消息、状态等。
1. autoReconnect: 当连接意外断开时,是否自动尝试重新连接。
2. heartbeat: 是否发送心跳消息以保持连接活跃。默认情况下,它会定期发送一个消息(默认为 'ping'),并期望服务器响应 'pong' 来确认连接有效。
下面是一个使用 useWebSocket 的 Vue 3 组件示例,包含连接状态管理、发送消息、接收消息和错误处理。</think>以下是对 `useWebSocket` 组合函数的详细解析和使用示例,特别关注 `autoReconnect` 和 `heartbeat` 参数的功能实现:
```vue
<template>
<div class="websocket-container">
<!-- 连接状态面板 -->
<el-card>
<template #header>
<div class="card-header">
<el-icon><Connection /></el-icon>
<span>WebSocket 连接管理</span>
</div>
</template>
<div class="status-display">
<el-tag :type="statusTagType" effect="dark" size="large">
{{ connectionStatusText }}
</el-tag>
<div class="stats">
<el-statistic title="接收消息" :value="stats.received" />
<el-statistic title="发送消息" :value="stats.sent" />
<el-statistic title="重连次数" :value="stats.reconnects" />
</div>
</div>
<div class="connection-controls">
<el-button
:type="isConnected ? 'danger' : 'primary'"
@click="toggleConnection"
>
{{ isConnected ? '断开连接' : '建立连接' }}
</el-button>
<el-button @click="clearMessages">清空记录</el-button>
</div>
</el-card>
<!-- 消息收发面板 -->
<el-card>
<template #header>
<div class="card-header">
<el-icon><Promotion /></el-icon>
<span>消息收发</span>
</div>
</template>
<el-input
v-model="messageToSend"
type="textarea"
:rows="4"
placeholder="输入要发送的消息..."
:disabled="!isConnected"
/>
<el-button
type="primary"
class="mt-3"
@click="sendMessage"
:disabled="!isConnected || !messageToSend"
>
发送消息
</el-button>
</el-card>
<!-- 消息记录面板 -->
<el-card>
<template #header>
<div class="card-header">
<el-icon><Memo /></el-icon>
<span>消息记录 ({{ messages.length }})</span>
</div>
</template>
<div class="message-list">
<div v-for="(msg, index) in messages" :key="index" class="message-item">
<div class="message-header">
<el-tag size="small" :type="msg.direction === 'in' ? 'success' : 'primary'">
{{ msg.direction === 'in' ? '接收' : '发送' }}
</el-tag>
<span class="timestamp">{{ formatTime(msg.timestamp) }}</span>
</div>
<div class="message-content">
{{ msg.content }}
}}
</div>
</div>
</div>
</el-card>
</div>
</template>
<script setup>
import { ref, computed, watch } from 'vue'
import { useWebSocket } from '@vueuse/core'
import { Connection, Promotion, Memo } from '@element-plus/icons-vue'
// WebSocket 服务器地址
const serverUrl = ref('wss://echo.websocket.org')
// 使用 VueUse 的 useWebSocket
const { status, data, send, close, open } = useWebSocket(serverUrl.value, {
// 自动重连配置
autoReconnect: {
retries: 10, // 最大重试次数
delay: 3000, // 重连延迟(ms)
onFailed() {
console.error('WebSocket 重连失败')
}
},
// 心跳检测配置
heartbeat: {
message: 'ping', // 发送的心跳消息
interval: 15000, // 心跳间隔(ms)
pongTimeout: 5000, // 等待pong响应超时时间
},
// 其他可选配置
immediate: true, // 是否立即连接
autoClose: false, // 是否在组件卸载时自动关闭
})
// 状态管理
const messages = ref([])
const messageToSend = ref('')
const stats = ref({
received: 0,
sent: 0,
reconnects: 0
})
// 计算属性
const isConnected = computed(() => status.value === 'OPEN')
const connectionStatusText = computed(() => {
const statusMap = {
'OPEN': '已连接',
'CONNECTING': '连接中...',
'CLOSED': '已断开',
'ERROR': '连接错误'
}
return statusMap[status.value] || status.value
})
const statusTagType = computed(() => {
const typeMap = {
'OPEN': 'success',
'CONNECTING': 'warning',
'CLOSED': 'info',
'ERROR': 'danger'
}
return typeMap[status.value] || 'info'
})
// 监听接收到的数据
watch(data, (newData) => {
if (!newData) return
// 处理心跳响应
if (newData === 'pong') {
addMessage('系统', '收到心跳响应', 'in')
return
}
// 处理普通消息
addMessage('服务器', newData, 'in')
stats.value.received++
})
// 监听状态变化
watch(status, (newStatus, oldStatus) => {
// 记录重连事件
if (oldStatus === 'ERROR' && newStatus === 'CONNECTING') {
stats.value.reconnects++
addMessage('系统', '尝试重新连接...', 'sys')
}
// 状态变化通知
const statusMessages = {
'OPEN': 'WebSocket 连接已建立',
'CLOSED': 'WebSocket 连接已关闭',
'ERROR': 'WebSocket 连接发生错误'
}
if (statusMessages[newStatus]) {
addMessage('系统', statusMessages[newStatus], 'sys')
}
})
// 添加消息到记录
function addMessage(source, content, direction) {
messages.value.push({
source,
content,
direction,
timestamp: new Date()
})
}
// 发送消息
function sendMessage() {
if (!isConnected.value || !messageToSend.value) return
send(messageToSend.value)
addMessage('我', messageToSend.value, 'out')
stats.value.sent++
messageToSend.value = ''
}
// 切换连接状态
function toggleConnection() {
if (isConnected.value) {
close()
} else {
open()
}
}
// 清空消息记录
function clearMessages() {
messages.value = []
}
// 时间格式化
function formatTime(date) {
return new Date(date).toLocaleTimeString()
}
</script>
<style scoped>
.websocket-container {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
gap: 20px;
max-width: 1200px;
margin: 0 auto;
padding: 20px;
}
.card-header {
display: flex;
align-items: center;
font-size: 18px;
font-weight: bold;
}
.card-header .el-icon {
margin-right: 8px;
}
.status-display {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 20px;
}
.stats {
display: flex;
gap: 15px;
}
.connection-controls {
display: flex;
gap: 10px;
margin-top: 15px;
}
.message-list {
max-height: 400px;
overflow-y: auto;
}
.message-item {
padding: 12px;
margin-bottom: 10px;
border-radius: 6px;
background-color: #f8f9fa;
border-left: 4px solid;
}
.message-item[data-direction="in"] {
border-left-color: #67c23a;
}
.message-item[data-direction="out"] {
border-left-color: #409eff;
}
.message-item[data-direction="sys"] {
border-left-color: #909399;
}
.message-header {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 8px;
}
.timestamp {
font-size: 12px;
color: #909399;
}
.message-content {
word-break: break-word;
}
</style>
```
### `useWebSocket` 参数详解:
1. **`autoReconnect` 自动重连机制**:
- 类型:`boolean | object`
- 默认值:`false`
- 功能:连接断开时自动尝试重新连接
- 配置选项:
```js
autoReconnect: {
retries: 3, // 最大重试次数(Infinity 表示无限重试)
delay: 1000, // 重连间隔时间(ms)
onFailed() { // 所有重试失败后的回调
console.error('重连失败')
}
}
```
2. **`heartbeat` 心跳检测机制**:
- 类型:`boolean | object`
- 默认值:`false`
- 功能:定期发送心跳包保持连接活跃
- 配置选项:
```js
heartbeat: {
message: 'ping', // 发送的心跳消息内容
interval: 30000, // 发送间隔(ms)
pongTimeout: 10000 // 等待响应超时时间(ms)
}
```
### 核心功能实现原理:
1. **自动重连流程**:
```mermaid
graph TD
A[连接断开] --> B{是否启用 autoReconnect?}
B -->|是| C[计算重连延迟]
C --> D[等待延迟时间]
D --> E[尝试重新连接]
E --> F{连接成功?}
F -->|是| G[继续正常通信]
F -->|否| H{达到最大重试次数?}
H -->|是| I[触发onFailed回调]
H -->|否| C
```
2. **心跳检测机制**:
```js
setInterval(() => {
send(heartbeatMessage)
const timer = setTimeout(() => {
if (!receivedPong) {
close() // 主动关闭超时连接
if (autoReconnect) reconnect()
}
}, pongTimeout)
}, heartbeatInterval)
```
3. **连接状态管理**:
- `OPEN`:连接已建立
- `CONNECTING`:连接中
- `CLOSED`:连接已关闭
- `ERROR`:连接错误
### 最佳实践建议:
1. **生产环境配置**:
```js
useWebSocket(serverUrl, {
autoReconnect: {
retries: Infinity, // 无限重试
delay: 5000 // 5秒重试间隔
},
heartbeat: {
message: JSON.stringify({ type: 'heartbeat' }),
interval: 25000,
pongTimeout: 8000
},
onConnected(ws) {
console.log('连接成功', ws)
},
onDisconnected() {
console.log('连接断开')
},
onError(err) {
console.error('连接错误', err)
}
})
```
2. **错误处理增强**:
```js
watch(status, (newStatus) => {
if (newStatus === 'ERROR') {
// 发送错误报告
logError('WebSocket连接错误')
}
})
```
3. **连接健康监控**:
```js
let lastActivity = Date.now()
watch(data, () => {
lastActivity = Date.now()
})
setInterval(() => {
if (Date.now() - lastActivity > 60000) {
close()
open() // 静默重启连接
}
}, 10000)
```
此实现完整展示了 `useWebSocket` 的核心功能,特别是 `autoReconnect` 和 `heartbeat` 参数的使用方法和配置技巧,适用于需要稳定 WebSocket 连接的实时应用场景。
阅读全文
相关推荐


















