本文介绍了在 Vue3 中使用 WebSocket 实现即时通讯的基础功能:
- 封装了可复用的 WebSocket 服务
- 实现了消息的发送和接收
- 提供了简单的 WebSocket 测试服务器
- 列出了可能的扩展方向
这个基础实现可以满足简单的实时通讯需求,根据项目需求可以在此基础上进行扩展。
WebSocket 是一种在单个 TCP 连接上进行全双工通信的协议,非常适合实现实时通讯功能。本文将介绍如何在 Vue3 项目中实现基础的 WebSocket 连接和消息收发功能。
第1步:封装WebSocket组合式函数
首先我们创建一个可复用的 WebSocket 组合式函数
,封装连接、发送和接收消息的逻辑,方便复用。
// src/hooks/websocket.js
import { ref } from 'vue'
/**
* WebSocket 服务封装
* @param {string} url WebSocket 服务器地址
* @returns {Object} 包含连接、发送、接收等方法
*/
export function useWebSocket(url) {
// 存储 WebSocket 实例
const socket = ref(null)
// 存储接收到的消息
const messages = ref([])
// 连接状态
const isConnected = ref(false)
/**
* 连接 WebSocket 服务器
*/
const connect = () => {
return new Promise((resolve, reject) => {
// 创建 WebSocket 连接
socket.value = new WebSocket(url)
// 连接成功回调
socket.value.onopen = () => {
isConnected.value = true
console.log('WebSocket connected')
resolve()
}
// 接收消息回调
socket.value.onmessage = (event) => {
// 将接收到的消息存入 messages 数组
const message = JSON.parse(event.data)
messages.value.push(message)
}
// 错误处理
socket.value.onerror = (error) => {
console.error('WebSocket error:', error)
reject(error)
}
// 连接关闭回调
socket.value.onclose = () => {
isConnected.value = false
console.log('WebSocket disconnected')
}
})
}
/**
* 发送消息
* @param {Object} message 要发送的消息对象
*/
const send = (message) => {
if (socket.value && isConnected.value) {
messages.value.push(message)//这里我将客户端发送的消息也推入消息队列
socket.value.send(JSON.stringify(message))
} else {
console.error('WebSocket is not connected')
}
}
/**
* 断开连接
*/
const disconnect = () => {
if (socket.value) {
socket.value.close()
}
}
return {
socket,
messages,
isConnected,
connect,
send,
disconnect
}
}
第2步:实现消息收发界面组件
接下来我们创建一个聊天组件,引入上面封装的 WebSocket 组合式函数
(当然WebSocket不止可以用来做聊天软件,凡是前后端双向通信的界面都可以这样用,所以下面的代码我隐藏了模板和样式)。
<!-- src/components/WebSocketDemo.vue -->
<script setup>
import { ref, onMounted, onUnmounted } from 'vue'
import { useWebSocket } from '@/hooks/useWebsockHook.js'
// 消息输入框
const newMessage = ref('')
// 初始化 WebSocket 连接
const { connect, send, messages, isConnected, disconnect } = useWebSocket('ws://localhost:8080')
// 组件挂载时连接 WebSocket
onMounted(() => {
connect().catch(err => {
console.error('Failed to connect:', err)
})
})
// 组件卸载时断开连接
onUnmounted(() => {
disconnect()
})
/**
* 发送消息
*/
const handleSend = () => {
if (newMessage.value.trim()) {
// 构造消息对象
const message = {
type: 'from_client', // 消息类型
content: newMessage.value, // 消息内容
timestamp: Date.now() // 时间戳
}
// 发送消息
send(message)
// 清空输入框
newMessage.value = ''
}
}
</script>
<template>
<div class="chat-container">
根据具体业务实现自己的模板
</div>
</template>
<style scoped>
</style>
第3步:测试 WebSocket 服务器(实际开发中,由后端提供)
为了测试我们的前端代码是否可以正常地运行,本例基于 Node.js 实现 WebSocket 服务器
// server.js
const WebSocket = require('ws')
// 创建 WebSocket 服务器,监听 8080 端口
const wss = new WebSocket.Server({ port: 8080 })
wss.on('connection', (ws) => {
console.log('New client connected')
// 收到客户端消息时回调
ws.on('message', (message) => {
console.log('Received:', message.toString())
// 简单回声处理:将收到的消息原样返回
wss.clients.forEach(client => {
if (client.readyState === WebSocket.OPEN) {
const msgObj = JSON.parse(message.toString())
msgObj.type = 'from_server'
msgObj.content = `我已收到消息:< ${msgObj.content} > 一切正常哦!`
client.send(JSON.stringify(msgObj))
}
})
})
ws.on('close', () => {
console.log('Client disconnected')
})
})
console.log('WebSocket server running on ws://localhost:8080')
启动服务:
node server.js
实现效果
注意事项
-
报错:Error: Cannot find module 'ws'
是因为项目缺少 WebSocket 服务器所需的ws
依赖包。需要进入项目目录, 安装 ws 模块 npm install ws -
发送消息,报错:WebSocket is not connected
说明连接尚未建立或已断开
注意端口,本例中的vite开发服务器默认端口是5173,不代表WebSocket服务器端口也是5173,他们是两个不同的服务,必须使用两个不同的端口 -
每次更改了服务都需要重新运行,没有运行代码变更就不会生效
补充:优化方向
本文只实现了基础功能,实际业务场景中还需要补充更多业务逻辑来保证可靠的服务
- 认证机制:添加 JWT 认证,确保连接安全
- 断线重连:自动重连机制,提高稳定性
- 心跳检测:保持连接活跃,检测断线
- 消息类型:区分系统消息、用户消息等
- 用户列表:显示用户状态
- 消息持久化:存储聊天记录到数据库
- 多房间/频道:支持不同的聊天房间
- ...