当前位置: 首页 > news >正文

UniApp ConnectSocket连接websocket

useSocket WebSocket 使用说明

项目地址

  • Node.js 服务端项目: https://gitee.com/node-server_yarn/node_test_learn.git
  • UniApp 客户端项目: https://gitee.com/uniapp_yarn/uniapp_socket_task.git

概述

useSocket 是一个基于 Vue 3 Composition API 的 WebSocket 封装 Hook,专为 UniApp 项目设计。它提供了完整的 WebSocket 连接管理、自动重连、心跳检测等功能,让您能够轻松地在 UniApp 项目中使用 WebSocket 进行实时通信。

功能特性

  • 自动连接管理 - 支持自动连接和手动连接
  • 自动重连机制 - 连接断开时自动重连,可配置重连次数和间隔
  • 心跳检测 - 定期发送心跳包保持连接活跃
  • 消息管理 - 自动解析和存储接收到的消息
  • 状态监控 - 实时监控连接状态和重连次数
  • 生命周期管理 - 组件卸载时自动断开连接
  • 错误处理 - 完善的错误处理和回调机制

安装和导入

1. 克隆项目

首先克隆相关项目到本地:

# 克隆 Node.js 服务端项目
git clone https://gitee.com/node-server_yarn/node_test_learn.git# 克隆 UniApp 客户端项目
git clone https://gitee.com/uniapp_yarn/uniapp_socket_task.git

2. 文件位置

useSocket.js 文件放置在项目的 src/hooks/ 目录下。

3. 导入方式

import {useSocket} from '@/hooks/useSocket';

基本使用

1. 最简单的使用方式

<template><view><text>连接状态: {{ isConnected ? '已连接' : '未连接' }}</text><button @click="sendMessage">发送消息</button></view>
</template><script setup>
import { useSocket } from '@/hooks/useSocket';// 创建 WebSocket 连接
const { isConnected, send, messages } = useSocket({url: 'ws://localhost:8080/ws',onMessage: (message) => {console.log('收到消息:', message);}
});// 发送消息
const sendMessage = () => {send({type: 'text',content: 'Hello WebSocket!'});
};
</script>

2. 完整配置示例

<template><view class="chat-container"><!-- 连接状态显示 --><view class="status-bar"><text>状态: {{ isConnected ? '已连接' : '未连接' }}</text><text v-if="reconnectCount > 0">重连次数: {{ reconnectCount }}</text></view><!-- 消息列表 --><scroll-view class="message-list" scroll-y><view v-for="message in messages" :key="message.timestamp" class="message-item"><text>{{ message.content }}</text></view></scroll-view><!-- 输入框 --><view class="input-area"><input v-model="inputText" placeholder="输入消息..." @confirm="handleSend" /><button @click="handleSend">发送</button></view></view>
</template><script setup>
import { ref } from 'vue';
import { useSocket } from '@/hooks/useSocket';const inputText = ref('');// 创建 WebSocket 连接
const {isConnected,reconnectCount,messages,connect,disconnect,send,clearMessages
} = useSocket({// WebSocket 服务器地址url: 'ws://localhost:8080/ws',// 最大重连次数maxReconnectCount: 5,// 重连间隔(毫秒)reconnectInterval: 3000,// 是否自动连接autoConnect: true,// 心跳间隔(毫秒)heartBeatInterval: 5000,// 连接成功回调onOpen: () => {console.log('WebSocket 连接成功');uni.showToast({title: '连接成功',icon: 'success'});},// 接收消息回调onMessage: (message) => {console.log('收到消息:', message);// 可以在这里处理不同类型的消息if (message.type === 'notification') {uni.showToast({title: message.content,icon: 'none'});}},// 连接错误回调onError: (error) => {console.error('WebSocket 错误:', error);uni.showToast({title: '连接错误',icon: 'error'});},// 连接关闭回调onClose: (event) => {console.log('WebSocket 连接关闭:', event);},// 达到最大重连次数回调onMaxReconnect: () => {console.log('已达到最大重连次数');uni.showModal({title: '连接失败',content: '无法连接到服务器,请检查网络连接',showCancel: false});}
});// 发送消息
const handleSend = async () => {if (!inputText.value.trim()) return;try {await send({type: 'text',content: inputText.value.trim(),timestamp: Date.now()});inputText.value = '';console.log('消息发送成功');} catch (error) {console.error('发送失败:', error);uni.showToast({title: '发送失败',icon: 'error'});}
};// 手动连接
const handleConnect = () => {connect();
};// 手动断开连接
const handleDisconnect = () => {disconnect();
};// 清空消息
const handleClearMessages = () => {clearMessages();
};
</script>

API 参考

useSocket(options)

参数 (options)
参数名类型默认值说明
urlstring''WebSocket 服务器地址
maxReconnectCountnumber5最大重连次数
reconnectIntervalnumber3000重连间隔(毫秒)
autoConnectbooleantrue是否自动连接
heartBeatIntervalnumber5000心跳间隔(毫秒)
onOpenfunction-连接成功回调
onMessagefunction-接收消息回调
onErrorfunction-连接错误回调
onClosefunction-连接关闭回调
onMaxReconnectfunction-达到最大重连次数回调
返回值
属性名类型说明
isConnectedref(boolean)连接状态
reconnectCountref(number)当前重连次数
messagesref(Array)消息列表
connectfunction手动连接方法
disconnectfunction断开连接方法
sendfunction发送消息方法
clearMessagesfunction清空消息方法

方法详解

connect()

手动建立 WebSocket 连接。

const {connect} = useSocket({url: 'ws://localhost:8080/ws'});
connect();
disconnect()

手动断开 WebSocket 连接。

const {disconnect} = useSocket({url: 'ws://localhost:8080/ws'});
disconnect();
send(data)

发送消息到服务器。

参数:

  • data (string | object): 要发送的数据,可以是字符串或对象

返回值: Promise

// 发送字符串
await send('Hello World');// 发送对象
await send({type: 'message',content: 'Hello World',timestamp: Date.now(),
});
clearMessages()

清空消息列表。

const {clearMessages} = useSocket({url: 'ws://localhost:8080/ws'});
clearMessages();

实际项目使用示例

聊天应用示例

<template><view class="chat-page"><!-- 聊天消息列表 --><scroll-view class="message-list" scroll-y :scroll-top="scrollTop"><view v-for="message in messages" :key="message.id" class="message-item"><view class="message-avatar"><image :src="message.avatar" mode="aspectFill" /></view><view class="message-content"><text>{{ message.content }}</text><text class="message-time">{{ message.timestamp }}</text></view></view></scroll-view><!-- 输入区域 --><view class="input-area"><inputv-model="inputText"placeholder="输入消息..."@confirm="handleSend":disabled="!isConnected"/><button@click="handleSend":disabled="!isConnected || !inputText.trim()">发送</button></view></view>
</template><script setup>
import { ref, onMounted, nextTick } from 'vue';
import { useSocket } from '@/hooks/useSocket';const inputText = ref('');
const scrollTop = ref(0);// 创建 WebSocket 连接
const { isConnected, messages, send } = useSocket({url: 'ws://localhost:8080/chat',onMessage: (message) => {console.log('收到聊天消息:', message);// 自动滚动到底部nextTick(() => {scrollToBottom();});},onOpen: () => {console.log('聊天连接已建立');},onError: (error) => {console.error('聊天连接错误:', error);uni.showToast({title: '连接失败',icon: 'error'});}
});// 发送消息
const handleSend = async () => {if (!inputText.value.trim() || !isConnected.value) return;const message = {type: 'text',content: inputText.value.trim(),timestamp: new Date().toLocaleTimeString(),id: Date.now()};try {await send(message);inputText.value = '';} catch (error) {console.error('发送消息失败:', error);uni.showToast({title: '发送失败',icon: 'error'});}
};// 滚动到底部
const scrollToBottom = () => {const query = uni.createSelectorQuery();query.select('.message-list').boundingClientRect();query.exec((res) => {if (res[0]) {scrollTop.value = res[0].height;}});
};onMounted(() => {// 页面加载时自动连接console.log('聊天页面已加载');
});
</script>

实时通知示例

<template><view class="notification-page"><view class="status-indicator" :class="{ connected: isConnected }"><text>{{ isConnected ? '在线' : '离线' }}</text></view><view class="notification-list"><viewv-for="notification in messages":key="notification.id"class="notification-item"><text>{{ notification.content }}</text><text class="notification-time">{{ notification.timestamp }}</text></view></view></view>
</template><script setup>
import { useSocket } from '@/hooks/useSocket';// 创建通知 WebSocket 连接
const { isConnected, messages } = useSocket({url: 'ws://localhost:8080/notifications',onMessage: (notification) => {console.log('收到通知:', notification);// 显示系统通知uni.showToast({title: notification.content,icon: 'none',duration: 3000});},onOpen: () => {console.log('通知连接已建立');}
});
</script>

注意事项

1. 网络环境

  • 确保 WebSocket 服务器地址正确且可访问
  • 在真机调试时,需要使用实际的 IP 地址而非 localhost

2. 生命周期管理

  • Hook 会在组件卸载时自动断开连接
  • 如需在多个组件间共享连接,建议使用全局状态管理

3. 错误处理

  • 建议为所有回调函数提供错误处理逻辑
  • 网络异常时会有自动重连机制,但达到最大重连次数后需要手动处理

4. 性能优化

  • 消息列表会持续增长,建议在适当时机调用 clearMessages() 清空
  • 心跳间隔不宜过短,避免频繁的网络请求

5. 平台兼容性

  • 本 Hook 基于 UniApp 的 uni.connectSocket API
  • 支持所有 UniApp 支持的平台(H5、小程序、App)

完整源码

useSocket.js 源码

// composables/useWebSocket.js
import {ref, reactive, onUnmounted} from 'vue';export function useSocket(options = {}) {// 状态const isConnected = ref(false);const reconnectCount = ref(0);const messages = ref([]);const socketTask = ref(null);// 配置const config = reactive({url: options.url || '',maxReconnectCount: options.maxReconnectCount || 5, // 最大重连次数reconnectInterval: options.reconnectInterval || 3000, // 重连间隔autoConnect: options.autoConnect !== false, // 自动连接heartBeatInterval: options.heartBeatInterval || 5000, // 心跳间隔...options,});// 心跳计时器let heartBeatTimer = null;// 连接 WebSocketconst connect = () => {if (socketTask.value) {disconnect();}// console.log('正在连接 WebSocket...');socketTask.value = uni.connectSocket({url: config.url,header: {'content-type': 'application/json',},success: () => {console.log('[WebSocket] 连接创建成功');},fail: (err) => {console.error('[WebSocket] 连接创建失败', err);options.onError?.(err);handleReconnect();},});bindEvents();};// 绑定事件const bindEvents = () => {if (!socketTask.value) return;socketTask.value.onOpen(() => {console.log('[WebSocket] 连接已打开');isConnected.value = true;reconnectCount.value = 0;options.onOpen?.();startHeartBeat();});socketTask.value.onMessage((res) => {const message = parseMessage(res.data);options.onMessage?.(message);messages.value.push(message);});socketTask.value.onError((err) => {console.error('[WebSocket] 连接错误:', err);isConnected.value = false;options.onError?.(err);handleReconnect();});socketTask.value.onClose((res) => {console.log('[WebSocket] 连接已关闭', res);isConnected.value = false;options.onClose?.(res);stopHeartBeat();});};// 发送消息const send = (data) => {if (!isConnected.value || !socketTask.value) {throw new Error('WebSocket 未连接');}const message = typeof data === 'string' ? data : JSON.stringify(data);return new Promise((resolve, reject) => {socketTask.value.send({data: message,success: () => {console.log('消息发送成功');resolve();},fail: (err) => {console.error('消息发送失败', err);reject(err);},});});};// 断开连接const disconnect = () => {if (socketTask.value && socketTask.value.readyState === 1) {socketTask.value.close();socketTask.value = null;}isConnected.value = false;stopHeartBeat();};// 重连机制const handleReconnect = () => {if (reconnectCount.value >= config.maxReconnectCount) {console.log('[WebSocket] 已达到最大重连次数');options.onMaxReconnect?.();return;}reconnectCount.value++;console.log(`[WebSocket] 尝试第 ${reconnectCount.value} 次重连...`);setTimeout(() => {connect();}, config.reconnectInterval);};// 解析消息const parseMessage = (data) => {try {return JSON.parse(data);} catch {return {type: 'text',content: data,timestamp: Date.now(),};}};// 心跳检测const startHeartBeat = () => {if (!config.heartBeatInterval) return;stopHeartBeat();heartBeatTimer = setInterval(() => {if (isConnected.value) {send({type: 'ping',timestamp: Date.now(),}).catch((err) => {console.error('[WebSocket] 心跳发送失败', err);});}}, config.heartBeatInterval);};const stopHeartBeat = () => {if (heartBeatTimer) {clearInterval(heartBeatTimer);heartBeatTimer = null;}};// 清空消息const clearMessages = () => {messages.value = [];};// 自动连接if (config.autoConnect && config.url) {connect();}// 组件卸载时清理onUnmounted(() => {disconnect();});return {// 状态isConnected,reconnectCount,messages,// 方法connect,disconnect,send,clearMessages,};
}

总结

useSocket Hook 为 UniApp 项目提供了完整的 WebSocket 解决方案,具有以下优势:

  1. 开箱即用 - 简单的 API 设计,快速上手
  2. 功能完整 - 包含连接管理、重连、心跳等完整功能
  3. 错误处理 - 完善的错误处理和回调机制
  4. 性能优化 - 自动清理和生命周期管理
  5. 易于扩展 - 基于 Vue 3 Composition API,易于扩展和定制

通过本说明文档,您应该能够快速在项目中使用 useSocket 实现 WebSocket 功能。如有任何问题,请参考示例代码或查看源码实现。
在这里插入图片描述

http://www.dtcms.com/a/406806.html

相关文章:

  • 正点原子【第四期】Linux之驱动开发学习笔记-5.1 设备树下的LED驱动实验
  • uniapp中全局封装一个跨组件的复制粘贴方法
  • 新奇特:神经网络烘焙坊(上),权重矩阵的甜蜜配方之谜
  • 分布式调度问题:定时任务
  • labelimg(目标检测标注工具)的安装、使用教程和问题解决
  • 【MFC】项目结构梳理
  • 中小企业声音克隆技术落地实践:痛点分析与轻量化解决方案建议
  • High precision single-photon object detection via deep neural networks,OE2024
  • 网站编程入门php做外贸网站好吗
  • 网站制作排名php自己写框架做网站
  • VMware+RockyLinux+ikuai+docker+cri-docker+k8s 自用 实践笔记(二)
  • Lambda
  • html网站开发代码公司网页设计实例教程
  • MySQL异步I/O性能优化全解析
  • SQL 执行计划解析:从 EXPLAIN 到性能优化的完整指南
  • jupyter notebook继续学习
  • 力扣2381. 字母移位 II
  • 平和县建设局网站安徽经工建设集团网站
  • Vue 配置代理
  • CatCTF2022 web wp
  • 知乎免费阅读网站石家庄新闻综合频道节目回看
  • 做网站后台主要负责什么最新室内装修风格图片
  • 机器人行业灵巧手专题研究报告
  • hive SQL查询与函数
  • 网站维护 关站 seo百度首页广告
  • 搜索引擎的网站有哪些网页设计与网站建设 倪宝童
  • Prompt Optimizer 提示词优化器安装使用
  • 淘宝网站建设的优点app推广是什么工作
  • 【C++】23. C++11(上)
  • 第三方软件登记测评机构:【LoadRunner脚本录制与调试】