Utilisation du message push WebSocket dans le projet Vue

1. Exigences fonctionnelles

1. C'est ce que j'ai utilisé dans le projet de gestion en arrière-plan. La fonction principale est de fournir une fonction de rappel de message.
2. Il y a principalement des invites dans le coin supérieur droit et une boîte de message dans le coin inférieur.
3. La fonction principale est que si l'utilisateur a des messages non lus, une boîte contextuelle apparaîtra lors de la première connexion. Si l'utilisateur ferme la page, la boîte contextuelle ne s'affichera plus lorsque la page est à nouveau actualisé. Cela signifie qu'un compte ne sera pas déconnecté auparavant. Lorsqu'il n'y a pas de message push en temps réel, la boîte de dialogue n'apparaîtra qu'une seule fois.
4. Si l'utilisateur clique sur un message non lu, le message sera placé dans l'historique (lu).
Affichage des pages :
Insérer la description de l'image ici

2. Code des pages

Remarque : le mien est un système de gestion en arrière-plan (utilisant vue-element-admin), et c'est la première fois que j'écris un websocket, je l'ai donc écrit sous le fichier src->layout->AppMain.vue :

<template>
  <section class="app-main">
    <Message-remind :message-list="messageList" />
    <transition name="fade-transform" mode="out-in">
      <keep-alive :include="cachedViews">
        <router-view :key="key" />
      </keep-alive>
    </transition>
  </section>
</template>

<script>
  import MessageRemind from '@/components/MessageRemind/index.vue'
  import { getToken, getSid } from "@/utils/auth"; // get token from cookie
  export default {
    name: 'AppMain',
    components: {
      MessageRemind
    },
    watch: {
      '$store.state.user': {
        handler: function (newValue, oldValue) {
          // 如果没有token,则表明退出了登录
          if (!newValue.token) {
            this.closeWebSocket();
          }
        },
        immediate: true,
        deep: true
      }
    },
    data() {
      return {
        // socket参数
        socket: null,
        timeout: 60 * 1000, // 45秒一次心跳
        timeoutObj: null, // 心跳心跳倒计时
        serverTimeoutObj: null, // 心跳倒计时
        timeoutnum: null, // 断开 重连倒计时
        lockReconnect: false, // 防止
        websocket: null,

        messageList: {}
      };
    },
    created() {
      const hasToken = getToken();
      const sid = getSid();
      if (hasToken) {
        this.initWebSocket(hasToken, sid)
      }
    },
    computed: {
      cachedViews() {
        return this.$store.state.tagsView.cachedViews
      },
      key() {
        return this.$route.path
      }
    },
    mounted() {
      // console.log(this.$store.state.tagsView.cachedViews)
    },
    methods: {
      initWebSocket(token, sid) {
        // WebSocket与普通的请求所用协议有所不同,ws等同于http,wss等同于https
        this.websocket = new WebSocket(process.env.VUE_APP_WEB_SOCKET_BASE_API + '?uiticket=' + token + '&sid=' + sid);
        this.websocket.onopen = this.websocketonopen;
        this.websocket.onerror = this.websocketonerror;
        this.websocket.onmessage = this.setOnmessageMessage;
        this.websocket.onclose = this.websocketclose;
        // 监听窗口关闭事件,当窗口关闭时,主动去关闭websocket连接,防止连接还没断开就关闭窗口,server端会抛异常。
        // window.onbeforeunload = that.onbeforeunload

      },

      start() {
        //清除延时器
        this.timeoutObj && clearTimeout(this.timeoutObj);
        this.serverTimeoutObj && clearTimeout(this.serverTimeoutObj);
        this.timeoutObj = setTimeout(() => {
          if (this.websocket && this.websocket.readyState == 1) {
            this.websocket.send('{"messageType": 99}');//发送消息,服务端返回信息,即表示连接良好,可以在socket的onmessage事件重置心跳机制函数
          } else {
            this.reconnect();
          }
          //定义一个延时器等待服务器响应,若超时,则关闭连接,重新请求server建立socket连接
          this.serverTimeoutObj = setTimeout(() => {
            this.websocket.close();
          }, this.timeout)
        }, this.timeout)
      },
      reset() { // 重置心跳
        // 清除时间
        clearTimeout(this.timeoutObj);
        clearTimeout(this.serverTimeoutObj);
        // 重启心跳
        this.start();
      },
      // 重新连接
      reconnect() {
        if (this.lockReconnect) return
        this.lockReconnect = true;
        //没连接上会一直重连,设置延迟避免请求过多
        this.timeoutnum && clearTimeout(this.timeoutnum);
        this.timeoutnum = setTimeout(() => {
          this.initWebSocket();
          this.lockReconnect = false;
        }, 5000)
      },
      async setOnmessageMessage(event) {
        this.messageList = JSON.parse(event.data)
        if (this.messageList.data.messageType === 999) {
          this.websocket.send('{"messageType": 99}');
        }
        this.$store.dispatch('user/steMessageMenu', this.messageList)
        this.reset();
        // 自定义全局监听事件
        window.dispatchEvent(new CustomEvent('onmessageWS', {
          detail: {
            data: event.data
          }
        }))
        //发现消息进入    开始处理前端触发逻辑
        // if (event.data === 'success' || event.data === 'heartBath') return
      },
      websocketonopen(e) {
        // console.log('onopen', {e});
        //开启心跳
        this.start();
        console.log("WebSocket连接成功!!!" + new Date() + "----" + this.websocket.readyState);
      },
      websocketonerror(e) {
        // console.log('websocketonerror', {e});
        console.log("WebSocket连接发生错误" + e);
      },
      websocketclose(e) {
        this.websocket.close();
        clearTimeout(this.timeoutObj);
        clearTimeout(this.serverTimeoutObj);
        console.log("WebSocket连接关闭");
      },
      websocketsend(messsage) {
        this.websocket.send(messsage)
      },
      closeWebSocket() { // 关闭websocket
        this.websocket.close()
      },
    },
  }
</script>

<style lang="scss" scoped>
  @import "~@/styles/global-height.scss";

  .app-main {
    /* 50= navbar  50  */
    // min-height: calc(100vh - #{$navbar+'px'});
    width: 100%;
    position: relative;
    overflow: hidden;
    display: flex;
    flex-direction: column;
    flex: 1;
  }

  .fixed-header+.app-main {
    padding-top: #{$navbar+'px'};
  }

  .hasTagsView {
    .app-main {
      // min-height: calc(100vh - #{$appMain+'px'});
    }

    .fixed-header+.app-main {
      padding-top: 90px;
    }
  }

  .copy {
    text-align: center;
    height: 30px;
    line-height: 30px;
    font-size: 13px;
    color: #666;
    background: #fff;
    width: 100%;
    box-shadow: 0 0 10px #dfe4ed;
  }
</style>

<style lang="scss">
  // fix css style bug in open el-dialog
  .el-popup-parent--hidden {
    .fixed-header {
      padding-right: 15px;
    }
  }
</style>

Je suppose que tu aimes

Origine blog.csdn.net/weixin_45849417/article/details/131380852
conseillé
Classement