Vue3+Ts+Vite項(xiàng)目websoket封裝使用方式
更新時(shí)間:2025年10月27日 09:48:20 作者:禮貌而已
文章介紹了如何封裝WebSocket并進(jìn)行頁(yè)面使用,包括安裝npm、創(chuàng)建websocket.ts文件、配置請(qǐng)求地址、全局類(lèi)型聲明以及在頁(yè)面中引用和注冊(cè)
一、安裝
- npm
npm install websocket --save-dev
- pnpm
pnpm install websocket --save-dev
二、封裝
在 /src/utils 文件夾下創(chuàng)建 websocket.ts 文件,并放入如下代碼
import { onUnmounted } from 'vue'
//設(shè)置
interface SocketOptions {
//心跳間隔
heartbeatInterval?: number
//超時(shí)重傳
reconnectInterval?: number
//最大重傳次數(shù)
maxReconnectAttempts?: number
}
class Socket {
//路徑
url: string
ws: WebSocket | null = null
opts: SocketOptions
//重傳次數(shù)
reconnectAttempts: number = 0
listeners: { [key: string]: Function[] } = {}
//心跳間隔
heartbeatInterval: number | null = null
//構(gòu)造函數(shù)
constructor(url: string, opts: SocketOptions = {}) {
this.url = url
this.opts = {
//心跳間隔
heartbeatInterval: 30000,
//超時(shí)重傳
reconnectInterval: 5000,
//最大重傳次數(shù)
maxReconnectAttempts: 5,
...opts
}
this.init()
}
//初始化
init() {
this.ws = new WebSocket(this.url)
this.ws.onopen = this.onOpen.bind(this)
this.ws.onmessage = this.onMessage.bind(this)
this.ws.onerror = this.onError.bind(this)
this.ws.onclose = this.onClose.bind(this)
}
//打開(kāi)
onOpen(event: Event) {
console.log('WebSocket opened:', event)
this.reconnectAttempts = 0
this.startHeartbeat()
this.emit('open', event)
}
//收到的WebSocket消息
onMessage(event: MessageEvent) {
// console.log('WebSocket message received:', event.data);
this.emit('message', event.data)
}
//錯(cuò)誤
onError(event: Event) {
console.error('WebSocket error:', event)
this.emit('error', event)
}
//重連邏輯中,在連接失敗后自動(dòng)重新連接
onClose(event: CloseEvent) {
console.log('WebSocket closed:', event)
this.stopHeartbeat()
this.emit('close', event)
//重連邏輯中,在連接失敗后自動(dòng)重新連接,但會(huì)限制重連的次數(shù)和每次重連之間的間隔時(shí)間
if (this.opts.maxReconnectAttempts !== 0 && this.reconnectAttempts < this.opts.maxReconnectAttempts!) {
setTimeout(() => {
// console.log("我有錯(cuò)誤了1111111111111111111111111111111111111");
this.reconnectAttempts++
this.init()
}, this.opts.reconnectInterval)
}
}
//開(kāi)始心跳檢測(cè)
startHeartbeat() {
if (!this.opts.heartbeatInterval) return
this.heartbeatInterval = window.setInterval(() => {
if (this.ws?.readyState === WebSocket.OPEN) {
this.ws.send('ping')
}
}, this.opts.heartbeatInterval)
}
//停止心跳檢測(cè)
stopHeartbeat() {
if (this.heartbeatInterval) {
clearInterval(this.heartbeatInterval)
this.heartbeatInterval = null
}
}
//發(fā)送消息
send(data: string) {
if (this.ws?.readyState === WebSocket.OPEN) {
this.ws.send(data)
} else {
console.error('WebSocket is not open. Cannot send:', data)
}
}
//事件監(jiān)聽(tīng)器注冊(cè)功能的實(shí)現(xiàn)
on(event: string, callback: Function) {
if (!this.listeners[event]) {
this.listeners[event] = []
}
this.listeners[event].push(callback)
}
//從事件監(jiān)聽(tīng)器中移除
off(event: string) {
if (this.listeners[event]) {
delete this.listeners[event]
}
}
//在事件監(jiān)聽(tīng)器中觸發(fā)一個(gè)指定的事件
emit(event: string, data: any) {
this.listeners[event]?.forEach(callback => callback(data))
}
}
export function useSocket(url: string, opts?: SocketOptions) {
const socket = new Socket(url, opts)
onUnmounted(() => {
socket.off('open')
socket.off('message')
socket.off('error')
socket.off('close')
socket.ws?.close() // 關(guān)閉WebSocket連接
})
return {
socket,
send: socket.send.bind(socket),
on: socket.on.bind(socket),
off: socket.off.bind(socket)
}
}
三、請(qǐng)求地址配置
3.1 將接口地址放到 public

3.2 引入 ipconfig.js 文件

3.3 全局類(lèi)型聲明
declare global {
/**
* Window 的類(lèi)型提示
*/
interface Window {
__APP_INFO__: __APP_INFO__
global_config: { wsURL: string }
}
}

四、頁(yè)面使用
4.1 引用
import { useSocket } from '@/utils/websocket'
4.2 注冊(cè)
// 注意:此處 useSocket() 中用的就是我們配置的全局地址
// 開(kāi)發(fā)結(jié)束,打包給后端,后端同時(shí)可以自行修改 ipconfig.js 文件中 websokect 地址,這樣部署上線之后 websokect 也能正常運(yùn)行
const { socket, on } = useSocket((window as any).global_config.wsURL)
on('close', () => console.log('Socket closed!'))
//webSocket連接上服務(wù)器時(shí)
on('open', (event: any) => {
console.log('webSocket連接上服務(wù)器時(shí)', event)
})
socket.on('message', (data: any) => {
if (data) {
// TODO: 此處拿到后端推送過(guò)來(lái)的數(shù)據(jù),進(jìn)行你后續(xù)的數(shù)據(jù)渲染邏輯
console.log(JSON.parse(data))
}
})
五、說(shuō)明

總結(jié)
以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。
相關(guān)文章
ElementUI中el-tree節(jié)點(diǎn)的操作的實(shí)現(xiàn)
這篇文章主要介紹了ElementUI中el-tree節(jié)點(diǎn)的操作的實(shí)現(xiàn),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2020-02-02
解決vue A對(duì)象賦值給B對(duì)象,修改B屬性會(huì)影響到A的問(wèn)題
今天小編就為大家分享一篇解決vue A對(duì)象賦值給B對(duì)象,修改B屬性會(huì)影響到A的問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2018-09-09
Vue結(jié)合echarts實(shí)現(xiàn)繪制水滴圖
這篇文章主要為大家詳細(xì)介紹了Vue如何結(jié)合echarts實(shí)現(xiàn)水滴圖的繪制,文中的示例代碼講解詳細(xì),感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下2023-07-07
apache和nginx下vue頁(yè)面刷新404的解決方案
這篇文章主要介紹了apache和nginx下vue頁(yè)面刷新404的解決方案,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-12-12
使用Vite+Vue3+TypeScript?搭建開(kāi)發(fā)腳手架的詳細(xì)過(guò)程
這篇文章主要介紹了Vite+Vue3+TypeScript?搭建開(kāi)發(fā)腳手架的詳細(xì)過(guò)程,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2023-02-02

