Vue3+Ts+Vite项目websoket封装使用方式

 更新时间:2025年10月27日 09:48:20   作者:礼貌而已  
文章介绍了如何封装WebSocket并进行页面使用,包括安装npm、创建websocket.ts文件、配置请求地址、全局类型声明以及在页面中引用和注册

一、安装

  • npm
npm install websocket --save-dev
  • pnpm
pnpm install websocket --save-dev

二、封装

在 /src/utils 文件夹下创建 websocket.ts 文件,并放入如下代码

import { onUnmounted } from 'vue'

//设置
interface SocketOptions {
  //心跳间隔
  heartbeatInterval?: number
  //超时重传
  reconnectInterval?: number
  //最大重传次数
  maxReconnectAttempts?: number
}

class Socket {
  //路径
  url: string
  ws: WebSocket | null = null
  opts: SocketOptions
  //重传次数
  reconnectAttempts: number = 0
  listeners: { [key: string]: Function[] } = {}
  //心跳间隔
  heartbeatInterval: number | null = null
  //构造函数
  constructor(url: string, opts: SocketOptions = {}) {
    this.url = url
    this.opts = {
      //心跳间隔
      heartbeatInterval: 30000,
      //超时重传
      reconnectInterval: 5000,
      //最大重传次数
      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)
  }
  //打开
  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)
  }
  //错误
  onError(event: Event) {
    console.error('WebSocket error:', event)
    this.emit('error', event)
  }
  //重连逻辑中,在连接失败后自动重新连接
  onClose(event: CloseEvent) {
    console.log('WebSocket closed:', event)
    this.stopHeartbeat()
    this.emit('close', event)
    //重连逻辑中,在连接失败后自动重新连接,但会限制重连的次数和每次重连之间的间隔时间
    if (this.opts.maxReconnectAttempts !== 0 && this.reconnectAttempts < this.opts.maxReconnectAttempts!) {
      setTimeout(() => {
        // console.log("我有错误了1111111111111111111111111111111111111");
        this.reconnectAttempts++
        this.init()
      }, this.opts.reconnectInterval)
    }
  }
  //开始心跳检测
  startHeartbeat() {
    if (!this.opts.heartbeatInterval) return

    this.heartbeatInterval = window.setInterval(() => {
      if (this.ws?.readyState === WebSocket.OPEN) {
        this.ws.send('ping')
      }
    }, this.opts.heartbeatInterval)
  }
  //停止心跳检测
  stopHeartbeat() {
    if (this.heartbeatInterval) {
      clearInterval(this.heartbeatInterval)
      this.heartbeatInterval = null
    }
  }
  //发送消息
  send(data: string) {
    if (this.ws?.readyState === WebSocket.OPEN) {
      this.ws.send(data)
    } else {
      console.error('WebSocket is not open. Cannot send:', data)
    }
  }
  //事件监听器注册功能的实现
  on(event: string, callback: Function) {
    if (!this.listeners[event]) {
      this.listeners[event] = []
    }
    this.listeners[event].push(callback)
  }
  //从事件监听器中移除
  off(event: string) {
    if (this.listeners[event]) {
      delete this.listeners[event]
    }
  }
  //在事件监听器中触发一个指定的事件
  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() // 关闭WebSocket连接
  })

  return {
    socket,
    send: socket.send.bind(socket),
    on: socket.on.bind(socket),
    off: socket.off.bind(socket)
  }
}

三、请求地址配置

3.1 将接口地址放到 public

3.2 引入 ipconfig.js 文件

3.3 全局类型声明

declare global {
  /**
   * Window 的类型提示
   */
  interface Window {
    __APP_INFO__: __APP_INFO__
    global_config: { wsURL: string }
  }
}

四、页面使用

4.1 引用

import { useSocket } from '@/utils/websocket'

4.2 注册

// 注意:此处 useSocket() 中用的就是我们配置的全局地址
// 开发结束,打包给后端,后端同时可以自行修改 ipconfig.js 文件中 websokect 地址,这样部署上线之后 websokect 也能正常运行
const { socket, on } = useSocket((window as any).global_config.wsURL)

on('close', () => console.log('Socket closed!'))
//webSocket连接上服务器时
on('open', (event: any) => {
  console.log('webSocket连接上服务器时', event)
})
socket.on('message', (data: any) => {
  if (data) {
   // TODO: 此处拿到后端推送过来的数据,进行你后续的数据渲染逻辑
   console.log(JSON.parse(data))
  }
})

五、说明

总结

以上为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。

相关文章

  • vue如何监听某个元素的大小变化

    vue如何监听某个元素的大小变化

    这篇文章主要介绍了vue如何监听某个元素的大小变化问题,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2023-10-10
  • vue实现画笔回放canvas转视频播放功能

    vue实现画笔回放canvas转视频播放功能

    这篇文章主要介绍了vue实现画笔回放,canvas转视频播放功能,本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2024-01-01
  • Vue3 中 watch 与 watchEffect 区别及用法小结

    Vue3 中 watch 与 watchEffect 区别及用法小结

    这篇文章主要介绍了Vue3 中 watch 与 watchEffect 有什么区别?watch中需要指明监视的属性,也需要指明监视的回调,而watchEffect中不需要指明监视的属性,只需要指明监视的回调,回调函数中用到哪个属性,就监视哪个属性,本文给大家详细介绍,需要的朋友参考下
    2022-06-06
  • Vue.js在使用中的一些注意知识点

    Vue.js在使用中的一些注意知识点

    这篇文章主要给大家介绍了Vue.js在使用中的一些注意知识点,文中介绍的非常详细,对大家学习或者使用Vue.js具有一定的参考学习价值,需要的朋友们下面来一起看看吧。
    2017-04-04
  • Vue之Axios异步通信详解

    Vue之Axios异步通信详解

    这篇文章主要为大家介绍了Vue之Axios异步通信,具有一定的参考价值,感兴趣的小伙伴们可以参考一下,希望能够给你带来帮助
    2021-11-11
  • vue-父子组件和ref实例详解

    vue-父子组件和ref实例详解

    这篇文章通过实例代码给大家介绍了vue-父子组件传值和ref获取dom和组件的方法,非常不错,具有一定的参考借鉴价值,需要的朋友可以参考下
    2019-11-11
  • Vue组件与生命周期详细讲解

    Vue组件与生命周期详细讲解

    Vue的生命周期就是vue实例从创建到销毁的全过程,也就是new Vue() 开始就是vue生命周期的开始。Vue 实例有⼀个完整的⽣命周期,也就是从开始创建、初始化数据、编译模版、挂载Dom -> 渲染、更新 -> 渲染、卸载 等⼀系列过程,称这是Vue的⽣命周期
    2022-10-10
  • Vue中使用Lodop插件实现打印功能的简单方法

    Vue中使用Lodop插件实现打印功能的简单方法

    这篇文章主要给大家介绍了关于Vue中使用Lodop插件实现打印功能的简单方法,文中通过示例代码介绍的非常详细,对大家学习或者使用Vue具有一定的参考学习价值,需要的朋友们下面来一起学习学习吧
    2019-12-12
  • vue实现购物车结算功能

    vue实现购物车结算功能

    这篇文章主要为大家详细介绍了vue实现购物车结算功能,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2020-06-06
  • 使用webpack手动搭建vue项目的步骤

    使用webpack手动搭建vue项目的步骤

    这篇文章主要介绍了从零使用webpack手动搭建vue项目的步骤,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2023-03-03

最新评论