新手小白 --- 学习把WebSocket放到全局调用 --- iview

小白第一次做大屏项目,第一次用到websocket绘制地图点位(一脸懵),第一次百度挣扎试过好多方法失败的,更有些摸不着头脑(更是一脸懵)。

       因项目需要,websocket必须做到全局才能使项目两模块都能用。第一次想着偷懒就把大屏做到管理系统里,用v-show达到切换目的同时websocket也同时在运行(真是个小天才~~嘻嘻~~),但暴露出很多v-show对echarts图的弊端o(╥﹏╥)o。后来不敢偷懒了,还是老老实实用vuex吧o(╥﹏╥)o

因为要做到全局,所以得用app.vue来实现目的。

App.vue是项目的主组件,页面入口文件 ,所有页面都在App.vue下进行切换,app.vue负责构建定义及页面组件归集。

同样光靠app.vue可不行,还得配合vuex来完美实现。
Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式, 采用集中式存储管理应用的所有组件的状态,解决多组件数据通信。
使用Vuex的好处:

1、数据的存取一步到位,不需要层层传递

2、数据的流动非常清晰

3、存储在Vuex中的数据都是响应式的

我用的框架是iview的admin plus,store方法都封装好了,用的比较轻松一些。

以下代码仅供参考,具体还是以自己项目为准

/** boolean常量 **/
let webSocket = {
    SYSTEM_HEADERS: 'system',
    BUSINESS_HEADERS: 'business',
    LOGIN_TYPE: 'login',
    HEARTBEAT_TYPE: 'heartbeat',
    CHAT_TYPE: 'chat',
    GAS_INDUSTRIAL_OR_RESIDENT: 'gasIndustrialOrResident',
    DEVICE_REAL_TIME_STATUS: 'deviceRealStatus',
    WEB_UPDATE_TIME: 'webUpdateTime',
    WS_READ_BELL: 'readBell',
    POLICE_TYPE: 'alarm',
    DEVICES: 'devices',
    ALLMAP_TYPE: 'batchMapPoints',
    ONLYMAP_TYPE: 'map',
    TIPS_TYPE: 'bell',
    BELL_BATCH_TYPE: 'bellList',
    BELL_WORK_TYPE: 'bellWork',
    TIME_TYPE: 'alarmScrolling',
    GET_ALL: 'getAll',
    TCP_MSG: 'tcpMsg'
}
/** 后台接口地址 **/
let urls = {
    /** ---------------------------------获取webscoket ip-----------------------------**/
    getWebscoketIP: BASEURL + supervisionApi + 'getWebSocketInfo',
}
export {
    urls, webSocket
}
import store from '../../store'
import { webSocket } from '@/js/constant';
 
import tools from '../tools'
import { Message } from 'view-design'
import { urls } from '../constant'
 
let ws;
 
/** webSocket报文格式,必须使用
 *  具体参照webSocket常量类,或者与后端联系1111111
 * **/
 
function message (obj) {
    /** 报文头,必填 **/
    this.headers = obj.headers
    /** 报文类型,必填 **/
    this.type = obj.type
    /** 消息发送者,必填 **/
    this.source = store.state.admin.user.info.Authorization
 
    /** 消息体 **/
    if (obj.message != null && undefined != obj.message) {
        this.message = obj.message
    }
    /** 内容接收者 **/
    if (obj.accept != null && undefined != obj.accept) {
        this.accept = obj.accept
    }
}
 
let WebsocketMessageService = {
    /** 获取ws实例 **/
    getWebSocket: function () {
        return this.ws
    },
 
    setWebSocket: function (ws) {
        this.ws = ws
    },
 
    closeWebSocket: function () {
        this.ws.close();
    },
 
    /** 通用消息发送方法 **/
    sendMessage: function (obj) {
        if (this.ws.readyState === 1) {
            this.ws.send(JSON.stringify(obj))
        }
    },
 
    /** 封装登录请求参数 **/
    setLoginMessage: function () {
        let params = new message({ headers: webSocket.SYSTEM_HEADERS, type: webSocket.LOGIN_TYPE })
        return params
    },
 
    /** 封装普通请求参数
     *  根据业务可自行调整具体的参数
     * **/
    setChatMessage: function (obj) {
        let params = new message({ headers: webSocket.BUSINESS_HEADERS, type: webSocket.CHAT_TYPE, message: obj.message })
        return params
    },
 
    /***
     * 心跳包
     * */
    setHeartbeat: function () {
        let params = new message({ headers: webSocket.BUSINESS_HEADERS, type: webSocket.HEARTBEAT_TYPE })
        return params
    },
 
    /**
     * 重新进图地图发送
     *
     * @param obj
     * @returns {message}
     */
    setWsAll: function (obj) {
        let params = new message({ headers: webSocket.BUSINESS_HEADERS, type: webSocket.GET_ALL, message: obj.message })
        return params
    },
 
    // 获取ip地址
    getWebSocketIP () {
        return new Promise((resolve, reject) => {
            tools.get(urls.getWebscoketIP).then(res => {
                if (res.success) {
                    resolve(res.obj)
                } else {
                    Message.error(res)
                }
            }).catch(error => {
                tools.doError(error)
            })
        })
    }
}
 
export {
    WebsocketMessageService
}

然后再app.vue中引入

<script>
import { WebsocketMessageService } from '@/js/system/websocketMessage';
import { webSocket, urls } from '@/js/constant';
//iview的admin plus的vuex
import { mapGetters, mapMutations, mapState } from 'vuex';
 
export default {
        name: 'app',
        data () {
            return {
                // websocket相关
                socketObj: '', // websocket实例对象
                // 心跳检测
                timeout: 10000, // 超时时间
                timeoutObj: null, // 计时器对象——向后端发送心跳检测
                serverTimeoutObj: null, // 计时器对象——等待后端心跳检测的回复
                // 心跳检测重置
                socketReconnectTimer: null, // 计时器对象——重连
                socketReconnectLock: false, // WebSocket重连的锁
                socketLeaveFlag: false, // 离开标记(解决 退出登录再登录 时出现的 多次相同推送 问题,出现的本质是多次建立了WebSocket连接)
            };
        },
        created () {
 
        },
        methods: {
            //iview的admin plus已封装好的vuex方法
            ...mapMutations('admin/websocket', [
                'setAllMap',
            ]),
            handleWindowResize () {
                this.handleMatchMedia();
            },
            handleMatchMedia () {
                const matchMedia = window.matchMedia;
 
                if (matchMedia('(max-width: 600px)').matches) {
                    this.setDevice('Mobile');
                } else if (matchMedia('(max-width: 992px)').matches) {
                    this.setDevice('Tablet');
                } else {
                    this.setDevice('Desktop');
                }
            },
            // websocket处理后台推送消息
            /** 发送消息 **/
            sendMessage (params) {
                WebsocketMessageService.sendMessage(params);
            },
            /** 连接websocket服务器 **/
            initWebSocket (ip) {
                console.log('webSocket 启用中。。。。 ');
                let _this = this;
                // 判断页面有没有存在websocket连接
                if (window.WebSocket) {
                    let ws = new WebSocket('ws://' + ip + '/ws');
                    /** 服务器连接成功 **/
                    ws.onopen = function (e) {
                        console.log('webSocket连接成功');
                        /** 发送频道注册消息 **/
                        _this.sendMessage(WebsocketMessageService.setLoginMessage());
                    };
                    /** 服务器连接关闭 **/
                    ws.onclose = function (e) {
                        console.log('webSocket连接关闭');
                        _this.heartbeatReset();
                    };
                    /** 服务器连接出错 **/
                    ws.onerror = function () {
                        console.log('webSocket连接出错,重新链接');
                        this.initWebSocket(ip);
                    };
                    /** 解析信息 **/
                    ws.onmessage = function (e) {
                        // 接收服务器返回的数据
                        let resData = JSON.parse(e.data);
                        switch (resData.headers) {
                        /** 系统级消息 **/
                        case webSocket.SYSTEM_HEADERS:
                            switch (resData.type) {
                            // 通道注册成功
                            case webSocket.LOGIN_TYPE:
                                /***
                                 * 建立心跳机制
                                 * */
                                _this.heartbeatReset();
                                _this.heartbeatStart();
                                break;
                            case webSocket.HEARTBEAT_TYPE:
                                /***
                                 * 收到心跳回复
                                 * */
                                _this.heartbeatReset();
                                _this.heartbeatStart();
                                break;
                            // 全点位
                            case webSocket.ALLMAP_TYPE:
                                _this.setAllMap(JSON.parse(resData.message))
                                console.log('地图点推送');
                                break;
                      
                            default:
                        }
                    };
                } else {
                }
 
                WebsocketMessageService.setWebSocket(_this.ws);
            },
            // websocket重连
            socketReconnect () {
                if (this.socketReconnectLock) {
                    return;
                }
                this.socketReconnectLock = true;
                this.socketReconnectTimer && clearTimeout(this.socketReconnectTimer);
                this.socketReconnectTimer = setTimeout(() => {
                    console.log('WebSocket:重连中...');
                    this.socketReconnectLock = false;
                    // websocket启动
                    WebsocketMessageService.getWebSocketIP().then((e) => {
                        /** 初始化websocket **/
                        this.initWebSocket(e);
                    }).catch((error) => {
                        this.heartbeatReset();
                        /** 接口异常,取消重新链接****/
                        this.$Message.error(error.errorMsg)
                    });
                }, 4000);
            },
            // 获取ip地址
            getWebsocketIp () {
                console.log('Authorization,', this.info.Authorization)
                WebsocketMessageService.getWebSocketIP().then((e) => {
                    /** 初始化websocket **/
                    this.initWebSocket(e);
                });
            },
 
            heartbeatReset () {
                clearTimeout(this.timeoutObj);
                clearTimeout(this.serverTimeoutObj);
            },
            heartbeatStart () {
                this.timeoutObj && clearTimeout(this.timeoutObj);
                this.serverTimeoutObj && clearTimeout(this.serverTimeoutObj);
                this.timeoutObj = setTimeout(() => {
                    // 这里向后端发送一个心跳检测,后端收到后,会返回一个心跳回复
                    WebsocketMessageService.sendMessage(WebsocketMessageService.setHeartbeat());
                    console.log('发送心跳检测');
                    this.serverTimeoutObj = setTimeout(() => {
                        // 如果超过一定时间还没重置计时器,开始重新链接,
                        console.log('未收到心跳检测回复');
                        this.socketReconnect()
                    }, this.timeout);
                }, this.timeout);
            },
            closeWebSocket () {
                this.ws.close();
            },
        },
        mounted () {
            this.getWebsocketIp();
        },
    }
</script>

然后再vuex中添加

 
export default {
    namespaced: true,
    state: {
        dataSpot: [],
    },
    mutations: {
        setAllMap (state, type) {
            state.dataSpot = type;
        },
    },
};

然后再地图文件中调用

import { mapState } from 'vuex';
 
computed: {
    ...mapState('admin/websocket', [
       'dataSpot',
     ])
},
 
watch: {
    dataSpot: {
         handler: function (newer, older) {
//绘制点位
            this.handlePoint()
         },
         deep: true
  },
}

小白第一次编写,如果问题,请见谅。如果能帮到你,十分荣幸!

  • 5
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值