1. 为什么你的Vue3项目需要WebSocket?
如果你正在用Vue3开发一个需要“即时感”的应用,比如在线聊天室、实时数据大屏、协同编辑文档,或者一个股票行情推送页面,那你肯定对传统的HTTP请求那种“一问一答”的模式感到头疼。用户发个消息,得等页面刷新或者手动点一下才能看到回复;数据更新了,用户不操作页面就永远看不到最新状态。这种体验,在今天看来已经有点“复古”了。
我刚开始做前端那会儿,为了实现一个简单的消息提醒,用的都是“轮询”(Polling)——就是让前端每隔几秒就发个请求去问问服务器:“有我的新消息吗?” 这种方法简单粗暴,但问题一大堆:浪费流量、增加服务器压力、消息还有延迟。后来接触到了WebSocket,感觉就像从绿皮火车换成了高铁,体验完全不一样了。
简单来说,WebSocket是一种在单个TCP连接上进行全双工通信的协议。你可以把它想象成在你和服务器之间拉了一根“专线电话”。电话一旦接通(连接建立),你们双方都可以随时说话(发送数据),也可以随时听到对方说话(接收数据),不需要反复地挂断再重拨。这对于需要服务器主动“推”数据给客户端的场景,简直是量身定做。
在Vue3里玩转WebSocket,特别是结合其强大的组合式API(Composition API),能让我们的代码组织得更加清晰、模块化,状态管理也更方便。接下来,我就带你从零开始,手把手搭建一个基于Vue3和原生WebSocket的实时聊天应用,把连接、收发消息、断线重连这些核心环节都摸透。
2. 环境准备与项目搭建
2.1 创建一个干净的Vue3项目
工欲善其事,必先利其器。我们首先需要一个Vue3项目作为舞台。这里我推荐使用Vite,它的启动速度和热更新体验都非常棒,能让我们更专注于逻辑开发。
打开你的终端,执行以下命令:
npm create vue@latest vue3-websocket-chat
执行后,命令行会交互式地让你选择一些配置。为了保持项目简洁,我们暂时不需要那么多高级功能,按照下面这样选择即可:
✔ Project name: … vue3-websocket-chat
✔ Add TypeScript? … No
✔ Add JSX Support? … No
✔ Add Vue Router for Single Page Application development? … No
✔ Add Pinia for state management? … No
✔ Add Vitest for Unit Testing? … No
✔ Add an End-to-End Testing Solution? › No
✔ Add ESLint for code quality? … No
选择完成后,进入项目目录并安装依赖:
cd vue3-websocket-chat
npm install
现在,你可以运行 npm run dev 来启动开发服务器。通常Vite会在 http://localhost:5173 启动你的应用。看到欢迎页面,说明项目骨架已经搭好了。
2.2 理解原生WebSocket API
在引入任何第三方库之前,我们先得搞清楚“地基”是什么。浏览器原生提供了 WebSocket 对象,使用起来其实非常直观。它的核心生命周期就几步:创建连接、监听事件、发送消息、关闭连接。
一个最最基础的用法长这样:
// 1. 创建连接,参数是服务器的WebSocket地址,以 ws:// 或 wss:// (加密) 开头
const socket = new WebSocket('ws://你的服务器地址');
// 2. 监听连接打开事件
socket.onopen = function(event) {
console.log('连接已建立', event);
// 连接成功后,可以在这里发送第一条消息
socket.send('Hello Server!');
};
// 3. 监听收到消息事件
socket.onmessage = function(event) {
console.log('收到服务器消息:', event.data);
// 通常数据是字符串,也可能是Blob或ArrayBuffer
};
// 4. 监听连接关闭事件
socket.onclose = function(event) {
console.log('连接已关闭', event.code, event.reason);
};
// 5. 监听错误事件
socket.onerror = function(error) {
console.error('WebSocket错误:', error);
};
// 主动发送消息
socket.send('这是一条文本消息');
// 主动关闭连接
socket.close(1000, '工作完成,正常关闭');
原生API虽然简单,但在实际项目中直接这样用会有点散乱,状态管理和错误处理都不太方便。接下来,我们就用Vue3的组合式API,把这些逻辑优雅地封装起来,让它变得可复用、好维护。
3. 在Vue3中封装一个健壮的WebSocket Hook
直接在每个组件里写一堆 onopen、onmessage 回调,代码会很快变得难以维护。Vue3的组合式API给了我们完美的解决方案:自定义Hook。我们可以把WebSocket的所有逻辑,包括连接、收发、重连,都封装到一个独立的、可复用的函数里。
3.1 创建 useWebSocket 基础版
我在 src/composables 目录下创建一个 useWebSocket.js 文件(如果你喜欢TypeScript,也可以用 .ts)。这个Hook将是我们整个实时功能的核心。
// src/composables/useWebSocket.js
import { ref, onUnmounted } from 'vue';
export default function useWebSocket(url) {
// 响应式数据:连接状态、收到的消息列表、错误信息
const socket = ref(null);
const isConnected = ref(false);
const messages = ref([]);
const error = ref(null);
// 建立连接
const connect = () => {
try {
// 如果已存在连接,先关闭
if (socket.value && socket.value.readyState === WebSocket.OPEN) {
socket.value.close();
}
// 创建新的WebSocket实例
const ws = new WebSocket(url);
socket.value = ws;
ws.onopen = () => {
console.log('WebSocket连接成功');
isConnected.value = true;
error.value = null;
// 可以在这里触发一个自定义事件,通知组件连接成功
};
ws.onmessage = (event) => {
console.log('收到消息:', event.data);
// 将新消息添加到列表头部,这样最新的消息显示在最上面
messages.value.unshift({
data: event.data,
time: new Date().toLocaleTimeString(),
type: 'received'
});
};
ws.onerror = (err) => {
console.error('WebSocket错误:', err);
error.value = '连接发生错误';
isConnected.value = false;
};
ws.onclose = (event) => {
console.log('连接关闭', event.code, event.reason);
isConnected.value = false;
// 如果不是正常关闭(code 1000),可以尝试自动重连
if (event.code !== 1000) {
console.warn('连接异常关闭,3秒后尝试重连...');
599



被折叠的 条评论
为什么被折叠?



