精华内容
下载资源
问答
  • Vue-WebSocket的使用
    2020-08-07 10:05:41
    data(){
        return{
            websock:null
        }
    }
    created() {
                this.initWebSocket()//初始化weosocket
            },
    methods:{
             /***初始化weosocket***/
                initWebSocket(){
                    const wsuri = `ws://192.168.0.0:8083/xxxxxx/websocket`//后端提供地址
                    this.websock = new WebSocket(wsuri);
                    this.websock.onmessage = this.websocketonmessage;
                    this.websock.onopen = this.websocketonopen;
                    this.websock.onerror = this.websocketonerror;
                    this.websock.onclose = this.websocketclose;
                },
                /***连接建立执行send方法发送数据***/
                websocketonopen(){
                    // this.websocketsend()
                },
                /***连接失败重新连接***/
                websocketonerror(){
                    this.initWebSocket()
                },
                /***接收数据***/
                websocketonmessage(result){
                    console.log('接收到新消息=',result)
                },
                /***数据发送***/
                websocketsend(data){//数据发送
                    console.log(data)
                    // this.websock.send(data)
                },
                /***断开连接***/
                websocketclose(e){ 
                    console.log('断开连接', e)
                }
    }
    更多相关内容
  • Vue-WebSocket原理及使用

    2021-08-02 16:47:34
    WebSocket就诞生了,它最大特点就是服务器可以主动向客户端推送信息,客户端也可以主动向服务器发送信息,是真正的双向平等对话,属于服务器推送技术的一种。 2、构造函数 let ws = new WebS...

    1、简介

            以前的http协议通信只能由客户端发起。如果我们想要了解今天的天气,只能是客户端向服务器发出请求,服务器返回查询结果。http协议做不到服务器主动向客户端推送信息。之前的做法就是使用轮询,每隔一段时间,就请求接口,了解服务器有没有新的信息,但是它效率低下,且非常浪费资源。WebSocket就诞生了,它最大特点就是服务器可以主动向客户端推送信息,客户端也可以主动向服务器发送信息,是真正的双向平等对话,属于服务器推送技术的一种。

    2、构造函数

    let ws = new WebSocket(wsServer);

    3、属性

    (1)webSocket.readyState

    • 0(WebSocket.CONNECTING):正在连接中,但还未建立
    • 1(WebSocket.OPEN):连接已经建立,可以进行通信
    • 2(WebSocket.CLOSING):连接正在关闭
    • 3(WebSocket.CLOSED):连接已关闭或者打开连接失败

    (2)webSocket.onopen

            定义一个事件处理程序,当readyState 变为1时调用,用于指定连接成功后的回调函数。

    ws.onopen = () => {
        console.log('连接已经建立,可以进行通信');
    }

    (3)webSocket.onmessage

            当收到来自服务器的消息时被调用。

    ws.onmessage = (e) => {
        let data = JSON.parse(e.data);
        console.log('接受到信息', data);
    }

    (4)webSocket.onclose

            用于指定连接关闭后的回调函数。

    ws.onclose = () => {
        console.log('服务器已经断开');
    }

    (5)webSocket.onerror

            用于指定报错时的回调函数。

    ws.onclose = (e) => {
        console.log(e);
    }

    4、方法

    (1)webSocket.send()

            用于向服务器发送数据。

    function fn(data) {
       if (ws.readyState === WebSocket.OPEN) {
              ws.send(data);
       } else {
          // Do something else in this case.
       }
    }

    (2)webSocket.close()

             关闭 WebSocket连接或连接尝试。

    ws.close();

    5、Vue中使用WebScoket

    <script>
        export default {
            name: 'Home',
            data() {
                return {
                    ws: null,
                }
            },
            methods: {
                // 启动websocket 获取列表数据
                initWebSocket() {
                    let _this = this;
                    let wsServer = (process.env.NODE_ENV === 'development'
                        ? "ws://10.196.254.168:8011"
                        : "wss://" + window.location.origin.split("//")[1])
                        + "/sctpacss/acs/event";
                    let limitConnect = 3;  // 断线重连次数
                    let timeConnect = 0;  // 当前重连次数
                    console.log(wsServer);
                    init();
    
                    // 初始化webSocket
                    function init() {
                        _this.ws = new WebSocket(wsServer);
                        _this.ws.onopen = () => {
                            console.log('TCP已连接');
                        }
                        _this.ws.onmessage = (e) => {
                            let data = JSON.parse(e.data);
                            console.log('接受到信息', data);
                        }
                        _this.ws.onclose = () => {
                            console.log('服务器已经断开');
                            reconnect();
                        }
                    }
    
                    // 重连
                    function reconnect() {
                        if (limitConnect > 0) {
                            limitConnect--;
                            timeConnect++;
                            console.log('第' + timeConnect + '次重连');
                            setTimeout(function () {
                                init();
                            }, 2000)
                        } else {
                            console.log('TCP连接已超时');
                        }
                    }
                },
    
                //关闭websocket
                closeWebSocket() {
                    if (this.ws) {
                        this.ws.close();
                        this.ws.onclose = function () {
                            console.log('websocket已关闭');
                        }
                    }
                },
            },
            mounted() {
                //绑定事件
                window.addEventListener('beforeunload', () => this.closeWebSocket())
                this.initWebSocket();
            },
            beforeDestroy() {
                //卸载事件
                window.removeEventListener('beforeunload', () => this.closeWebSocket());
            },
        }
    </script>
    展开全文
  • nodejs-websocket 基于node创建websocket服务器 websocket 协议和 http 协议类似,http 协议有一个缺陷,只能由客户方端发起请求,服务端根据请求 url 和传过去的参数返回对应结果 websocket 是双向通信的,只要 ...
  • Vuejs 使用 vue-native-websocket

    千次阅读 2020-09-25 15:32:38
    yarn add vue-native-websocket # or npm install vue-native-websocket --save 使用 一、配置 通过URL字符串自动进行websocket连接 import VueNativeSock from 'vue-native-websocket' Vue.use(VueNativeSock, ...

    安装

    yarn add vue-native-websocket
    
    # or
    
    npm install vue-native-websocket --save
    
    

    使用

    一、配置

    通过URL字符串自动进行websocket连接

    import VueNativeSock from 'vue-native-websocket'
    Vue.use(VueNativeSock, 'ws://localhost:9090')
    

    二、连接实例

    1、自动连接

    启用ws自动重新连接(适用于整个系统多方面应用websocket接收消息):

    import Vue from 'vue'
    import VueNativeSock from 'vue-native-websocket'
    const socketUrl  = 'ws://' + window.location.host + '/hh-web/webSocket';
    
    Vue.use(VueNativeSock, socketUrl, {
        reconnection: true, // 自动重新连接 (false)
        reconnectionAttempts: Infinity, // 重新连接尝试次数 (Infinity),
        reconnectionDelay: 2000, // 重新连接时间间隔
      })
    

    2、手动连接

    启用ws手动连接(适用于系统单个页面接收处理websocket消息):

    import Vue from 'vue'
    import VueNativeSock from 'vue-native-websocket'
    const socketUrl  = 'ws://' + window.location.host + '/hh-web/webSocket';
    
    Vue.use(VueNativeSock, socketUrl, {
        connectManually: true,  //是否手动连接ws
        reconnectionAttempts: Infinity, // 重新连接尝试次数 (Infinity),
        reconnectionDelay: 2000, // 重新连接时间间隔
      })
    

    3、关于Vuejs实例的用法

    var vm = new Vue({
      methods: {
        clickButton: function(val) {
            // $socket is [WebSocket](https://developer.mozilla.org/en-US/docs/Web/API/WebSocket) instance
            this.$socket.send('some data')
            // or with {format: 'json'} enabled
            this.$socket.sendObj({awesome: 'data'})
        }
      }
    })
    

    4、创建和删除动态websocket事件监听器

    创建一个新的动态监听器

    this.$options.sockets.onmessage = (data) => console.log(data)
    

    删除现有监听器

    delete this.$options.sockets.onmessage
    
    

    三、应用实例

    自定义websocket事件处理
    1、事件名称
    2、函数定义
    3、原始/默认处理程序代码功能function (eventName, event)。这使您可以选择将事件移交给原始处理程序之前进行一些基本的预处理。
    这是执行一些预处理,然后将事件传递到原始处理程序代码的示例:

    实例

    1、新建websocket/index.js文件

    在这里插入图片描述

    2、在入口函数中引入websocket文件

    import { useSocket } from './modules/websocket'
    useSocket()
    
    

    3、编写websocket文件,自定义websocket事件处理

    3.1、引入websocket组件、定义常量
    import Vue from 'vue'
    import VueNativeSock from 'vue-native-websocket'
    
    const socketUrl  = 'ws://' + window.location.host + '/hh-web/webSocket';
    
    /* 定义并导出接收socket后触发的自定义在事件名 -- start */
    export const debugEvent = 'debugEvent'
    /* 定义并导出接收socket后触发的自定义在事件名 -- end */
    
    3.2、定义useSocket函数
    
    let socketBus
    
    function useSocket () {
      Vue.use(VueNativeSock, socketUrl, {
        reconnection: true, // 自动重新连接 (false)
        reconnectionAttempts: Infinity, // 重新连接尝试次数 (Infinity),
        reconnectionDelay: 2000, // 重新连接时间间隔
      })
      socketBus = new Vue()  //vue实例,用来绑定动态监听器 onclosed onmessage等事件
      socketBus.$options.sockets.onclose = () => {
        console.log('websocket closed')
      }
      socketBus.$options.sockets.onmessage = (e) => {
        let data
        try {
          data = JSON.parse(e.data)
        } catch (e) {
          console.log(e)
          data = null
        }
        handleSocketData(data)  //数据处理函数
      }
    }
    
    3.3、编写数据处理函数
    function handleSocketData (data) {
      if (!data) {
        return
      }
      switch (+data.eventType) {
        case 3:  // 设备调试返回结果
        socketBus.$emit(debugEvent, data)  //子组件向父组件传递debugEvent事件和data数据
          break;
      }
    }
    
    3.4、暴露定义的变量,以便父组件引用使用
    export { useSocket, socketUrl, socketBus }
    

    4、组件product.vue中使用websocket事件

    import { socketBus, debugEvent } from '@/modules/websocket'
    
     mounted () {
        socketBus.$on(debugEvent, this.dealResult)  //sockeBus绑定debugEvent事件
      },
      beforeDestroy () {
        socketBus.$off(debugEvent)     //sockeBus解绑debugEvent事件
      }
    
    
    展开全文
  • vue-native-websocket-vue3' import * as types from './store/mutation-types/socket' import App from './App.vue' const muconst app = createApp(App) tations = { 0: types....
  • vue手把手带你创建聊天室(vue-native-websocket) 谓套接字(Socket),就是对网络中不同主机上的应用进程之间进行双向通信的端点的抽象。一个套接字就是网络上进程通信的一端,提供了应用层进程利用网络协议交换数据...

    vue手把手带你创建聊天室(vue-native-websocket)

    谓套接字(Socket),就是对网络中不同主机上的应用进程之间进行双向通信的端点的抽象。一个套接字就是网络上进程通信的一端,提供了应用层进程利用网络协议交换数据的机制。从所处的地位来讲,套接字上联应用进程,下联网络协议栈,是应用程序通过网络协议进行通信的接口,是应用程序与网络协议根进行交互的接口
    [1] 。

    正文开始:
    socket中使用了VUEX如果不打算使用状态管理器,可以忽略下文中的某些配置。

    在vue中我们使用:vue-native-websocket
    第一步安装:

    npm install vue-native-websocket --save
    

    然后在main.js中进行全局注册:

    Vue.use(VueNativeSock,"后台地址*****",{
      // 启用Vuex集成
      store: store,
      // 数据发送/接收使用使用json
      format: "json",
      connectManually: true,
      reconnection: true,
     // 尝试重连的次数
     reconnectionAttempts: 5,
     // 重连间隔时间
     reconnectionDelay: 3000,
      passToStoreHandler: function (eventName, event) {
        if (!eventName.startsWith('SOCKET_')) { return }
        let method = 'commit';
        let target = eventName.toUpperCase();
        let msg = event;
        if (this.format === 'json' && event.data) {
          msg = JSON.parse(event.data);
          if (msg.mutation) {
            target = [msg.namespace || '', msg.mutation].filter((e) => !!e).join('/');
          } else if (msg.action) {
            method = 'dispatch';
            target = [msg.namespace || '', msg.action].filter((e) => !!e).join('/');
          }
        }
        this.store[method](target, msg);
        this.store.state.socket.message = msg;
      }
    });
    

    第三部写html:
    在一个.vue结尾的文件中写入一下代码:

    <!--公用组件:消息内容展示,实现群聊和单聊业务-->
    <template>
        <div id="mainContent" >
            <div class="top-panel" ref="topPanel">
                <div class="title-panel">
                    <!-- <p>当前在线人数: {{onlineUsers}}</p> -->
                </div>
            </div>
            <!--消息显示-->
            <div class="messages-panel" ref="messagesContainer">
                <div class="row-panel" v-for="(item,index) of senderMessageList" :key="index">
                    <!--发送者消息样式-->
                    <div class="sender-panel" v-if="item.userID == userID">
                        <!--昵称展示-->
                        <div class="user-name-panel sender">
                            <p>{{item.username}}</p>
                        </div>
                        <!--消息-->
                        <div class="msg-body">
                            <!--消息尾巴-->
                            <div class="tail-panel">
                                <svg class="icon" aria-hidden="true">
                                    <use xlink:href="#icon-zbds30duihuakuangyou" color="#dce7dc"></use>
                                </svg>
                            </div>
                            <!--消息内容-->
                            <p v-html="item.msgText" @click="viewLargerImage($event)" ref="comment"/>
                        </div>
                        <!--头像-->
                        <div class="avatar-panel">
                            <img :src="item.avatarSrc" alt="">
                        </div>
                    </div>
                    <!--对方消息样式-->
                    <div class="otherSide-panel" v-else>
                        <!--头像-->
                        <div class="avatar-panel">
                            <img :src="item.avatarSrc" alt="">
                        </div>
                        <!--昵称展示-->
                        <div class="user-name-panel sender">
                            <p>{{item.username}}</p>
                        </div>
                        <!--消息-->
                        <div class="msg-body">
                            <!--消息尾巴-->
                            <div class="tail-panel">
                                <svg class="icon" aria-hidden="true">
                                    <use xlink:href="#icon-zbds30duihuakuangzuo"></use>
                                </svg>
                            </div>
                            <!--消息内容-->
                            <p v-html="item.msgText" @click="viewLargerImage($event)" ref="comment" />
                        </div>
                    </div>
                </div>
            </div>
            <!--用户输入模块-->
            <div class="user-input-panel" @click="getEditableDivFocus()">
                <div class="toolbar-panel">
                    <div class="item-panel" v-for="(item ,index) of toolbarList" :key="index">
                        <img class="emoticon" :src="require(`../assets/img/${item.src}`)"
                             @mouseenter="toolbarSwitch('hover',$event,item.src,item.hover,item.down,item.name)"
                             @mouseleave="toolbarSwitch('leave',$event,item.src,item.hover,item.down,item.name)"
                             @mousedown="toolbarSwitch('down',$event,item.src,item.hover,item.down,item.name)"
                             @mouseup="toolbarSwitch('up',$event,item.src,item.hover,item.down,item.name)" :alt="item.info">
                    </div>
                </div>
                <div id="msgInputContainer" class="input-panel" ref="msgInputContainer" @keydown.enter.exact="sendMessage($event)"
                     contenteditable="true" spellcheck="false">
                </div>
                 <div class="send-panel" ref="sendPanel" @click="mobileSend()">
                        <p>发送</p>
                    </div>
                <!--表情面板-->
                <div class="emoticon-panel" :style="{display: emoticonShowStatus}" ref="emoticonPanel">
                    <div class="row-panel">
                        <div class="item-panel" v-for="(item,index) of this.emojiList" :key="index">
                            <img :src="require(`../assets/images/emoji/${item.src}`)" :alt="item.info"
                                 @mouseover="emojiConversion($event,'over',item.src,item.hover,item.info)"
                                 @mouseleave="emojiConversion($event,'leave',item.src,item.hover,item.info)"
                                 @click="emojiConversion($event,'click',item.src,item.hover,item.info)">
                        </div>
                    </div>
                    <div class="ico-panel"></div>
                </div>
            </div>
        </div>
    </template>
    
    <script src="../assets/js/message-display.js"></script>
    
    <style lang="scss" src="../assets/css/message-display.scss" scoped></style>
    

    style文件:

    #mainContent {
      width: 100%;
      height: 100%;
    
      .top-panel {
        width: 100%;
        height: 30px;
        display: flex;
        align-items: center;
        border-bottom: 1px solid #cecece;
    
        .title-panel {
          width: 70%;
          height: 25px;
          display: flex;
          align-items: center;
    
          .equipmentType {
            width: 18px;
            height: 18px;
            margin-left: 5px;
    
            img {
              width: 100%;
              height: 100%;
            }
          }
        }
    
        /*操作栏样式:单聊*/
        .operate-panel {
          width: 29%;
          height: 25px;
    
          .ico-panel {
            width: 100%;
            height: 100%;
            display: flex;
            justify-content: flex-end;
            align-items: center;
    
            .item-panel {
              width: 20px;
              height: 20px;
    
              img {
                width: 100%;
                height: 100%;
              }
            }
          }
        }
    
        /*操作栏样式:群聊*/
        // .operate-group-panel{
    
        // }
      }
    
      ::-webkit-scrollbar {
        width: 2px;
        /*滚动条宽度*/
        height: 6px;
        /*滚动条高度*/
      }
    
      .messages-panel {
        width: 100%;
        min-height: 400px !important;
        overflow-y: auto;
        max-height: 800px;
        overflow-x: hidden;
        padding-top: 5px;
        padding-bottom: 15px;
    
        .row-panel {
          width: 100%;
          min-height: 50px;
    
          /*对方消息样式*/
          .otherSide-panel {
            width: 96%;
            min-height: 50px;
            display: flex;
            margin-bottom: 15px;
            position: relative;
    
            .avatar-panel {
              width: 30px;
              min-width: 30px;
              height: 30px;
              border-radius: 50%;
              overflow: hidden;
    
              img {
                width: 100%;
                height: 100%;
              }
            }
    
            .user-name-panel {
              width: 240px;
              height: 20px;
              position: absolute;
              left: 42px;
              top: 2px;
              display: flex;
              justify-content: flex-start;
    
              align-items: center;
    
              p {
                color: #9da9c6;
                white-space: nowrap;
                overflow: hidden;
                text-overflow: ellipsis;
              }
            }
    
            .msg-body {
              max-width: 95%;
              min-height: 40px;
              background: #f4f3f3;
              border-radius: 5px;
              display: flex;
              align-items: center;
              padding: 10px;
              box-sizing: border-box;
              margin-top: 28px;
              margin-left: 16px;
              position: relative;
    
              /*消息尾巴*/
              .tail-panel {
                width: 20px;
                height: 100%;
                position: absolute;
                left: -10px;
                svg {
                  margin-top: 8px;
                  color: #f3f3f3;
                }
               
              }
    
              p {
                font-size: 12px;
                /*自动换行*/
                word-wrap: break-word;
                overflow: hidden;
                cursor: pointer;
    
                img {
                  width: 100%;
                  height: 100%;
                }
              }
            }
          }
    
          /*发送者消息样式*/
          .sender-panel {
            width: 96%;
            min-height: 50px;
            float: right;
            margin-right: 12px;
            display: flex;
            justify-content: flex-end;
            margin-bottom: 15px;
            position: relative;
    
            .avatar-panel {
              width: 30px;
              min-width: 30px;
              height: 30px;
              border-radius: 50%;
              overflow: hidden;
    
              img {
                width: 100%;
                height: 100%;
              }
            }
    
            .user-name-panel {
              width: 240px;
              height: 20px;
              position: absolute;
              right: 42px;
              top: 2px;
              overflow: hidden;
              text-overflow: ellipsis;
              display: flex;
              justify-content: flex-end;
              align-items: center;
    
              p {
                color: #9da9c6;
                white-space: nowrap;
                overflow: hidden;
                text-overflow: ellipsis;
              }
            }
    
            .msg-body {
              max-width: 95%;
              min-height: 40px;
              background: #d8e8dc;
              border-radius: 5px;
              display: flex;
              align-items: center;
              padding: 10px;
              box-sizing: border-box;
              margin-top: 28px;
              margin-right: 16px;
              position: relative;
              /*消息尾巴*/
              .tail-panel {
                width: 20px;
                height: 100%;
                position: absolute;
                right: -18px;
                svg {
                  margin-top: 8px;
                  color: #f3f3f3;
                }
              }
    
              p {
                font-size: 12px;
                line-height: 23px;
                // 强制换行
                word-break: break-all;
                display: flex;
                align-items: center;
                cursor: pointer;
                img {
                  width: 100%;
                  height: 100%;
                  display: block;
                }
              }
            }
          }
        }
      }
    
      .send-panel {
        width: 70px;
        height: 30px;
        background-image: linear-gradient(-90deg, #29bdd9 0%, #276ace 100%);
        text-align: center;
        color: white;
        border-radius: 5px;
        line-height: 30px;
        cursor: pointer;
        float: right;
        margin-right: 5px;
      }
      .user-input-panel {
        width: 100%;
        height: 160px;
        position: relative;
        border-top: 1px solid #cecece;
    
        .toolbar-panel {
          width: 100%;
          height: 40px;
          display: flex;
          align-items: center;
    
          .item-panel {
            width: 24px;
            height: 24px;
            margin-right: 20px;
            display: flex;
            justify-content: center;
            align-items: center;
    
            img {
              width: 100%;
              height: 100%;
            }
          }
    
         
        }
       
        .input-panel {
          width: 100%;
          min-height: 30px;
          max-height: 120px;
          overflow-y: auto;
          outline: none;
          display: flex;
          align-items: center;
          flex-flow: row wrap;
          // 强制换行
          word-break: break-all;
        }
    
        /*表情面板*/
        .emoticon-panel {
          width: 290px;
          height: 250px;
          border-radius: 5px;
          background: white;
          border: solid 1px #dfe0e0;
          padding: 20px;
          box-sizing: border-box;
          position: absolute;
          top: -260px;
          // left: -194px;
          display: flex;
          justify-content: flex-start;
          z-index: 9999999;
         
          .row-panel {
            width: 100%;
            height: 30px;
            display: flex;
            align-items: center;
            flex-flow: row wrap;
    
            .item-panel {
              width: 25px;
              height: 25px;
              margin-right: 6px;
              margin-bottom: 7px;
              position: relative;
              // 取消12的倍数的元素的右外边距
              // &:nth-child(12n){
              //   margin-right: 0;
              // }
    
              img {
                width: 100%;
                height: 100%;
    
                &:hover {
                  width: 26px;
                  height: 26px;
                }
              }
            }
          }
    
          .ico-panel {
            width: 0;
            height: 0;
            border-right: 6px solid transparent;
            border-left: 6px solid transparent;
            border-top: 6px solid #dfe0e0;
            position: absolute;
            bottom: -6px;
            img {
              width: 100%;
              height: 100%;
            }
          }
        }
      }
    }
    

    JS:

    import emoji from '../json/emoji';
    import toolbar from '../json/toolbar';
    import lodash from 'lodash';
    import base from "./base";
    import VueCookies from "vue-cookies";
    
    
    
    export default {
        name: "message-display",
        data() {
            return {
                danmu: null,
                id: '1',
                roomid: '',
                images: [],
                userID: '',
                worker:null,
                ws:null,
                isHide:true,
                messagesContainerTimer: "",
                onlineUsers: this.$store.state.onlineUsers,
                createDisSrc: require("../img/titlebar_function_createDis_normal@2x.png"),
                resourceObj: {
                    createDisNormal: require("../img/titlebar_function_createDis_normal@2x.png"),
                    createDisHover: require("../img/titlebar_function_createDis_hover@2x.png"),
                    createDisClick: require("../img/titlebar_function_createDis_normal_p@2x.png"),
                    phoneNormal: require("../img/phone_normal_ap@2x.png"),
                    groupMsgImg: require("../img/group-msg-img.png"),
                    avatarImg: require("../img/avatar.jpg"),
                    msgImgTest: require("../img/msg-img-test.gif"),
                    msgImgTestB: require("../img/msg-img-testB.gif"),
                },
                // 消息内容
                messageContent: "",
                InputContent: "",
                emoticonShowStatus: "none",
                emojiList: emoji,
                toolbarList: toolbar,
                senderMessageList: [],
                audioCtx: null,
                // 声音频率
                arrFrequency: [
                    196.00, 220.00, 246.94, 261.63, 293.66, 329.63, 349.23, 392.00, 440.00, 493.88, 523.25, 587.33, 659.25, 698.46, 783.99, 880.00, 987.77, 1046.50
                ],
                testWorker: null
            }
        },
        mounted: function () {
            let that = this
            let uid = this.$cookies.get('u_id')
            let course_id = this.$route.query.id
            let s_id = this.$cookies.get('s_id')
            let tokens = this.$cookies.get('PHPSESSID')
            this.$store.commit("changeCourse", {
                uid: uid,
                s_id: s_id,
                name: course_id
            });
            function work() {
                onmessage = ({ data: { jobId, message ,classID} }) => {
                    postMessage({ jobId, result: message});
                };
            }
            const makeWorker = f => {
                let hide = that.isHide
                let pendingJobs = {};
                let worker = new Worker(
                    URL.createObjectURL(new Blob([`(${f.toString()})()`])) //Blob = Binary Large Object的缩写,直译为二进制大对象
                );
                worker.onmessage = ({ data: { result, jobId,classID } }) => {
                  
                    let  ws = new WebSocket('wss://apps.beiqujy.com/count' +`?room_id=${result[0][0]}&uid=${result[0][1]}&type=3&from=2&class_id=${result[1]}`)
                    ws.onopen = function () {
                        let login_data = '{"type":3,"from":2,"client_name":"' + '' + '","room_id":"' + result[0][0]+ '","class_id":"' + result[1] + '","uid":"' + result[0][1] + '"}';
                        console.log(login_data)
                        ws.send('首次发送消息'+login_data);
                    };
                    ws.onmessage = function (evt) {
                        var received_msg = evt.data;
                    
                    };
                    ws.onclose = function () {
                        if(that.isHide){
                            reconnect('wss://apps.beiqujy.com/count' +`?room_id=${result[0][0]}&uid=${result[0][1]}&type=3&from=2&class_id=${result[1]}`)
                        }
                    };
                    function reconnect(url) {
                        var connects
                        clearTimeout(connects);
                        connects = setTimeout(function () {     //没连接上会一直重连,设置延迟避免请求过多
                            var ws = new WebSocket(url);
                            ws.onopen = function () {
                                let login_data = '{"type":3,"from":2,"client_name":"' + '' + '","room_id":"' + result[0][0]+ '","class_id":"' + result[1] + '","uid":"' + result[0][1] + '"}';
                                console.log('重连后发送的消息'+login_data)
                                ws.send(login_data);
                            };
                            ws.onmessage = function (evt) {
                                var received_msgs = evt.data;
                              
                            };
                            ws.onclose = function () {
                             
                                if(that.isHide){
                                    reconnect('wss://apps.beiqujy.com/count' +`?room_id=${result[0][0]}&uid=${result[0][1]}&type=3&from=2&class_id=${result[1]}`)
                                }
                            };
                        }, 5000);
                    }
                    // 调用resolve,改变Promise状态
                    pendingJobs[jobId](result);
                    // 删掉,防止key冲突
                    delete pendingJobs[jobId];
                };
                return (...message) =>
                    new Promise(resolve => {
                        const jobId = String(Math.random());
                        pendingJobs[jobId] = resolve;
                        worker.postMessage({ jobId, message });
                    });
            };
            this.testWorker = makeWorker(work);    
            this.$nextTick(() => {
                this.testWorker([VueCookies.get("roomid"), this.$store.state.uid],this.$route.query.id).then(message => {
                });
            });
            //链接socket
            this.$connect(process.env.VUE_APP_SOCKET + `?course_id=${course_id}&uid=${uid}&type='students'&from=2&listen_id=123`);
            this.userID = this.$store.state.uid
            var i = 0
            // webAudioAPI兼容性处理
            window.AudioContext = window.AudioContext || window.webkitAudioContext;
            // 设置列容器高度
            this.$refs.messagesContainer.style.height = this.getThisWindowHeight() - 350 + "px";
            // 全局点击事件,点击表情框以外的地方,隐藏当前表情框
            document.addEventListener('click', (e) => {
                let thisClassName = e.target.className;
                if (thisClassName !== "emoticon-panel" && thisClassName !== "emoticon") {
                    this.emoticonShowStatus = "none";
                }
            });
            //从本地存储中获取数据渲染页面
            this.renderPage("", "", 1);
            // 监听消息接收
            this.$options.sockets.onmessage = (res) => {
                const data = JSON.parse(res.data);
                console.log(data)
                // this.messageChange()
                this.$store.commit("changeMessage", {
                    msg: data.data.message
                });
                if (data.code == 201 || data.code == 202  ) {
                    return
                } else {
                    // this.$store.state.onlineUsers = data.onlineUsers;
                    // 更新在线人数
                    // this.onlineUsers = data.onlineUsers;
                    // 获取服务端推送的消息
                    const msgObj = {
                        msg: data.data.msg,
                        avatarSrc: data.data.user_img,
                        userID: data.data.uid,
                        username: data.data.user_nicename
                    };
                    if (lodash.isEmpty(localStorage.getItem("msgArray"))) {
                        this.renderPage(JSON.parse(localStorage.getItem("msgArray")), msgObj, 0);
                    } else {
                        this.renderPage(JSON.parse(localStorage.getItem("msgArray")), msgObj, 0);
                    }
                }
            };
        },
        beforeDestroy() {
            // 页面销毁时,断开连接
            localStorage.setItem("msgArray", '[]')
            this.isHide = false
            this.closeWorker()
            this.$disconnect();
        },
        methods: {
            closeWorker() {
                // console.log(this.testWorker)
                // this.worker.terminate()
                this.testWorker=null
            },
            createDisEventFun: function (status) {
                if (status === "hover") {
                    this.createDisSrc = this.resourceObj.createDisHover
                } else if (status === "leave") {
                    this.createDisSrc = this.resourceObj.createDisNormal
                } else {
                    this.createDisSrc = this.resourceObj.createDisClick
                }
            },
            getThisWindowHeight: () => window.innerHeight,
            getThisWindowWidth: () => window.innerWidth,
            sendMessage: function (event) {
                if (event.keyCode === 13) {
                    // 阻止编辑框默认生成div事件
                    event.preventDefault();
                    let msgText = "";
                    // 获取输入框下的所有子元素
                    let allNodes = event.target.childNodes;
                    for (let item of allNodes) {
                        // 判断当前元素是否为img元素
                        if (item.nodeName === "IMG") {
                            msgText += `/${item.alt}/`;
                        } else {
                            // 获取text节点的值
                            if (item.nodeValue !== null) {
                                msgText += item.nodeValue;
                            }
                        }
                    }
                    // 消息发送: 发送文字,为空则不发送
                    if (msgText.trim().length > 0) {
                        var obj = {
                            uid: parseInt( this.$cookies.get('u_id')),
                            message: msgText,
                            type:'students',
                            from:2,
                            event:1,
                            listen_id:123,
                            course_id: parseInt( this.$route.query.id)
                            
                        }
                        this.$socket.sendObj(obj)
                        event.target.innerHTML = "";
                    }
                }
            },
            mobileSend: function () {
                // 模拟触发回车事件
                this.fireKeyEvent(this.$refs.msgInputContainer, 'keydown', 13);
            },
            //  渲染页面
            renderPage: function (msgArray, msgObj, status) {
                if (status === 1) {
                    // 页面第一次加载,如果本地存储中有数据则渲染至页面
                    let msgArray = [];
                    if (localStorage.getItem("msgArray") !== null) {
                        msgArray = JSON.parse(localStorage.getItem("msgArray"));
                        for (let i = 0; i < msgArray.length; i++) {
                            const thisSenderMessageObj = {
                                "msgText": msgArray[i].msg,
                                "msgId": i,
                                "avatarSrc": msgArray[i].avatarSrc,
                                "userID": msgArray[i].userID,
                                "username": msgArray[i].username
                            };
                            // 更新消息内容
                            this.messageContent = msgArray[i].msg;
                            // 向父组件传值
                            this.$emit('updateLastMessage', this.messageContent);
                            // 解析并渲染
                            this.messageParsing(thisSenderMessageObj);
                        }
                    }
                } else {
                    // 判断本地存储中是否有数据
                    if (localStorage.getItem("msgArray") === null) {
                        // 新增记录
                        msgArray.push(msgObj);
                        // 更新消息内容
                        this.messageContent = msgObj.msg;
                        // 向父组件传值
                        this.$emit('updateLastMessage', this.messageContent);
                        localStorage.setItem("msgArray", JSON.stringify(msgArray));
                        for (let i = 0; i < msgArray.length; i++) {
                            const thisSenderMessageObj = {
                                "msgText": msgArray[i].msg,
                                "msgId": i,
                                "avatarSrc": msgArray[i].avatarSrc,
                                "userID": msgArray[i].userID,
                                "username": msgArray[i].username
                            };
                            // 解析并渲染
                            this.messageParsing(thisSenderMessageObj);
                        }
                    } else {
                        // 更新记录
                        msgArray = JSON.parse(localStorage.getItem("msgArray"));
                        msgArray.push(msgObj);
                        localStorage.setItem("msgArray", JSON.stringify(msgArray));
                        // 更新消息内容
                        this.messageContent = msgObj.msg;
                        // 向父组件传值
                        this.$emit('updateLastMessage', this.messageContent);
                        const thisSenderMessageObj = {
                            "msgText": msgObj.msg,
                            "msgId": Date.now(),
                            "avatarSrc": msgObj.avatarSrc,
                            "userID": msgObj.userID,
                            "username": msgObj.username
                        };
                        // 解析并渲染
                        this.messageParsing(thisSenderMessageObj);
                    }
                }
            },
            // 模拟触发事件
            fireKeyEvent: function (el, evtType, keyCode) {
                let doc = el.ownerDocument,
                    win = doc.defaultView || doc.parentWindow,
                    evtObj;
                if (doc.createEvent) {
                    if (win.KeyEvent) {
                        evtObj = doc.createEvent('KeyEvents');
                        evtObj.initKeyEvent(evtType, true, true, win, false, false, false, false, keyCode, 0);
                    } else {
                        evtObj = doc.createEvent('UIEvents');
                        Object.defineProperty(evtObj, 'keyCode', {
                            get: function () {
                                return this.keyCodeVal;
                            }
                        });
                        Object.defineProperty(evtObj, 'which', {
                            get: function () {
                                return this.keyCodeVal;
                            }
                        });
                        evtObj.initUIEvent(evtType, true, true, win, 1);
                        evtObj.keyCodeVal = keyCode;
                        if (evtObj.keyCode !== keyCode) {
                            console.log("keyCode " + evtObj.keyCode + " 和 (" + evtObj.which + ") 不匹配");
                        }
                    }
                    el.dispatchEvent(evtObj);
                } else if (doc.createEventObject) {
                    evtObj = doc.createEventObject();
                    evtObj.keyCode = keyCode;
                    el.fireEvent('on' + evtType, evtObj);
                }
            },
            // 消息解析
            messageParsing: function (msgObj) {
                console.log(msgObj)
                // 解析接口返回的数据进行渲染
                let separateReg = /(\/[^/]+\/)/g;
                let msgText = msgObj.msgText;
                let finalMsgText = "";
                if(msgText && msgText != undefined){
                    // 将符合条件的字符串放到数组里
                    const resultArray = msgText.match(separateReg);
               
                if (resultArray !== null) {
                    for (let item of resultArray) {
                        // 删除字符串中的/符号
                        item = item.replace(/\//g, "");
                        // 判断是否为图片: 后缀为.jpeg
                        if (this.isImg(item)) {
                            const imgSrc = `${base.lkBaseURL}/uploads/chatImg/${item}`;
                            // 获取图片宽高
                            let imgInfo = {
                                "imgWidth": this.getQueryVariable(imgSrc, "width"),
                                "imgHeight": this.getQueryVariable(imgSrc, "height")
                            };
                            let thisImgWidth = 0;
                            let thisImgHeight = 0;
                            if (imgInfo.imgWidth < 400) {
                                thisImgWidth = imgInfo.imgWidth;
                                thisImgHeight = imgInfo.imgHeight;
                            } else {
                                // 缩放四倍
                                thisImgWidth = imgInfo.imgWidth / 4;
                                thisImgHeight = imgInfo.imgHeight / 4;
                            }
                            // 找到item中?位置,在?之前添加\\进行转义,解决正则无法匹配特殊字符问题
                            const charIndex = item.indexOf("?");
                            // 生成正则表达式条件,添加\\用于对?的转义
                            const regularItem = this.insertStr(item, charIndex, "\\");
                            // 解析为img标签
                            const imgTag = `<img width="${thisImgWidth}" height="${thisImgHeight}" src="${imgSrc}" alt="聊天图片">`;
                            // 替换匹配的字符串为img标签:全局替换
                            msgText = msgText.replace(new RegExp(`/${regularItem}/`, 'g'), imgTag);
                        }
                        // 表情渲染: 遍历表情配置文件
                        for (let emojiItem of this.emojiList) {
                            // 判断捕获到的字符串与配置文件中的字符串是否相同
                            if (emojiItem.info === item) {
                                const imgSrc = require(`../img/emoji/${emojiItem.hover}`);
                                const imgTag = `<img src="${imgSrc}" width="28" height="28" alt="${item}">`;
                                // 替换匹配的字符串为img标签:全局替换
                                msgText = msgText.replace(new RegExp(`/${item}/`, 'g'), imgTag);
                            }
                        }
                    }
                    finalMsgText = msgText;
                } else {
                    finalMsgText = msgText;
                }
            }
                msgObj.msgText = finalMsgText;
                // 渲染页面
                this.senderMessageList.push(msgObj);
                let hash = {}
                this.senderMessageList = this.senderMessageList.reduce((prev, array) => {
                    if (array.username == undefined) {
                        hash[array.username] ? '' : hash[array.username] = true && prev.push(array)
                    } else {
                        prev.push(array)
                    }
                    return prev
                }, [])
                // 修改滚动条位置
                this.$nextTick(function () {
                    this.$refs.messagesContainer.scrollTop = this.$refs.messagesContainer.scrollHeight;
                });
            },
            // 显示表情
            toolbarSwitch: function (status, event, path, hoverPath, downPath, toolItemName) {
                if (status === "hover" || status === "up") {
                    event.target.src = require(`../img/${hoverPath}`);
                } else if (status === "leave") {
                    event.target.src = require(`../img/${path}`);
                } else {
                    // 可编辑div获取焦点
                    this.getEditableDivFocus();
                    event.target.src = require(`../img/${downPath}`);
                    // 表情框显示条件
                    if (toolItemName === "emoticon") {
                        if (this.emoticonShowStatus === "flex") {
                            this.emoticonShowStatus = "none";
                        } else {
                            this.emoticonShowStatus = "flex";
                        }
                    } else {
                        this.emoticonShowStatus = "none";
                    }
                }
            },
            // 判断一个对象是否为函数类型
            isFunction: function (obj) {
                return typeof obj === "function" && typeof obj.nodeType !== "number";
            },
            // 表情框鼠标悬浮显示动态表情
            emojiConversion: function (event, status, path, hoverPath, info) {
                if (status === "over") {
                    event.target.src = require(`../img/emoji/${hoverPath}`);
                } else if (status === "click") {
                    // 表情输入
                    const imgSrc = require(`../img/emoji/${hoverPath}`);
                    const imgTag = `<img src="${imgSrc}" width="28" height="28" alt="${info}">`;
                    document.execCommand("insertHTML", false, imgTag);
                } else {
                    event.target.src = require(`../img/emoji/${path}`);
                }
            },
            // base64转file
            convertBase64UrlToImgFile: function (urlData, fileName, fileType) {
                // 转换为byte
                let bytes = window.atob(urlData);
                // 处理异常,将ascii码小于0的转换为大于0
                let ab = new ArrayBuffer(bytes.length);
                let ia = new Int8Array(ab);
                for (let i = 0; i < bytes.length; i++) {
                    ia[i] = bytes.charCodeAt(i);
                }
                // 转换成文件,添加文件的type,name,lastModifiedDate属性
                let blob = new Blob([ab], { type: fileType });
                blob.lastModifiedDate = new Date();
                blob.name = fileName;
                return blob;
            },
            // 判断是否为图片
            isImg: function (str) {
                return str.indexOf(".jpeg") !== -1;
            },
            viewLargerImage: function (event) {
                const imgSrc = event.target.src;
                if (typeof imgSrc !== "undefined") {
                    // 清空图片数组
                    this.images = [];
                    this.images.push(imgSrc);
                    this.show();
                }
            },
            // 获取url参数
            getQueryVariable: function (url, variable) {
                // 对url进行截取
                url = url.substring(url.indexOf("?"), url.length);
                var query = url.substring(1);
                var vars = query.split("&");
                for (var i = 0; i < vars.length; i++) {
                    var pair = vars[i].split("=");
                    if (pair[0] == variable) { return pair[1]; }
                }
                return false;
            },
            // 字符串指定位置添加字符
            insertStr: function (source, start, newStr) {
                return source.slice(0, start) + newStr + source.slice(start);
            },
            // 可编辑div获取焦点
            getEditableDivFocus: function () {
                // 开头获取焦点
                this.$refs.msgInputContainer.focus();
            },
            // 图片查看插件
            show() {
                const viewer = this.$el.querySelector('.images').$viewer
                viewer.show()
            }
        },
    }
    

    至于表情包和一些聊天小组件,有需要的童鞋可以留言。

    展开全文
  • 下载 zip 包并解压并将vue-stomp.js文件从 dist 文件夹添加到您的项目中。 https://github.com/FlySkyBear/vue-stomp/archive/master.zip 用法 注册插件,它将连接到/ import VueStomp from "vue-stomp" ; Vue ....
  • 具体实现 /** 连接 */ connectWebSocket() { if ('WebSocket' in window) { this.websocket = new WebSocket(process.env.VUE_APP_WS_BASE_API + '') this.initWebSocket() } else { alert('当前浏览器不支持...
  • npm i rpc-websocket-client 特征 带有注释文档的TypeScript 。 唯一RPC标识符。 轻巧。 如果您想忽略标准以获得更好的性能,则可以调用noRpc()方法来防止从所有消息中发送jsonrpc: '2.0'开销。 使用changeSocket...
  • vue-websocket的使用

    千次阅读 2020-05-24 10:22:49
    vue前端项目开发过程中需要实时显示部分数据,在通过多个处理方式中选择使用websocket来解决这个问题。 解决方案 vue单页代码 export default { // 关闭页面时断开socket连接 beforeDestroy () { this....
  • vue封装websocket.zip

    2020-02-24 20:49:11
    vue 封装 webSocket调用 封装后的webSocket在组件中调用 压缩文件中包含socket.js和调用方法说明
  • java实现类似好友列表在线离线状态实时检测,用户状态实时检测,监听浏览器关闭销毁session,websocket长链接全局登录时调用,也可应用于实时聊天并判断好友在线离线
  • vue-websocket使用方法?

    2017-09-15 04:33:33
    vue-websocketvue+webpack搭建的项目里如何使用?求大神解决一下
  • vue - websocket

    2021-07-10 17:38:08
    <script> export default { data() { path:"https://127.0.0.1:8888/websocket/", ... // 实例化socket,这里的实例化直接赋值给this.ws是为了后面可以在其它的函数中也能调用websocket方法,例如:this.w
  • vue-webtopo-svgeditor 纯vue3实现的svg可视化web布局编辑器。主要用于物联网mqtt实时系统图 预览地址 如何使用 # 克隆项目 git clone https://github.com/yaolunmao/vue-webtopo-svgeditor.git # 进入项目目录 cd ...
  • 本篇文章将与各位开发者分享下 vue-native-websocket 库的使用以及配置,通过实例代码给大家分享Vue通过配置WebSocket并实现群聊功能,需要的朋友可以参考下
  • 近年来随着 Web 前端的快速发展,浏览器新特性层出不穷,越来越多的应用可以在浏览器端或通过浏览器渲染引擎实现,Web 应用的即时通信方式 WebSocket 得到了广泛的应用。 WebSocket 是一种在单个 TCP 连接上进行全...
  • golang-websocket:使用golang和vite.js进行项目测试websocket
  • 在本篇文章里小编给大家整理的是关于vue-socket.io跨域问题有效解决方法,对此有兴趣的朋友们可以参考下。
  • Vue-Socket.io是Vuejs的socket.io集成,易于使用,支持Vuex和组件级套接字使用者管理 演示版 您在寻找旧的文档吗? :rocket: 安装 npm install vue-socket.io --save 使用连接字符串 import Vue from 'vue' import ...
  • 安装nodejs-websocket,运行命令npm install nodejs-websocket 创建server.js const ws = require('nodejs-websocket'); const moment = require('moment'); const hostName = '127.0.0.1'; let clients = {}; //...
  • robust-websocket, 用于浏览器的强大的重新连接 web socket客户端 强大的web socket 强大的。重新连接浏览器的web socket客户机 robust-websocket 是在实现相同接口的标准 web socket web socket类的包装器,但当...
  • 本文旨在记录使用Flask框架过程中与前端Vue对接过程中,存在WebSocket总是连接失败导致前端取不到数据的问题。以及在使用WebSocket相关功能的库包gevent-websocket之后,导致运行Flask项目之后,控制台没有显示...
  • websocket接收消息推送+语音提示 这个是同事的代码,我拿来记录一下,希望以后可以看得懂…… ... install: function (Vue){ let Socket = '' let setIntervalWesocketPush = null let socketUrl = ''
  • 主要介绍集成 WebSocket 将服务端消息发送到客户端以及底层调用逻辑分析。
  • vue结合websocket

    2022-04-22 12:47:52
    1. vue结合websocket 本人首先是写java后端的,我也是第一次接触websocekt,当然前端也接触的也少,但是楼主已经默默的学会了flex布局,下面的是做的测试页面,写的不好还请谅解。下面时本人总结的websocket可以直接...
  • 主要介绍了Vue+Java 通过websocket实现服务器与客户端双向通信操作,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
  • VueWebsocket

    千次阅读 2021-07-26 16:04:46
    话不多说,直接上代码吧 <script> export default { name: "indexPage", ... websock: null, //websocket对象 maxReconnect: 5, //最大重连次数 }; }, methods: { /** * 监听方法 */ // 初始化webS
  • 1、前端框架:Vue + element-ui 2、后端框架:SpringBoot + Mybatis 3、数据库:H2 4、其他第三方工具或者插件: Jsch:用于远程连接ECS服务器。 Websocket:与前端进行实时交互。 xterm:渲染web版本的terminal终端...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 15,779
精华内容 6,311
关键字:

vue-websocket

友情链接: danchunxingfa.rar