Vue作为一个单页面应用, webSocket可以说是用起来非常爽了.
因为webSocket在同一个html文件中,是可以保持连接的.
但是当使用f5或者点击刷新页面以后, websocket连接就会强制关闭. 关于这个问题我研究了很久,最后找到两种解决办法;
先说下我踩过的坑,起初我设想,在登录并创建websocket连接成功后,设置一个字段保存在localStorage或者cookie中:
每次路由发生变化时,如果已登录但connSocket值為0,则创建socket连接,否则不处理;
设想很美好, 然而实际操作过程中, 发现页面手动f5或按钮刷新时,
根本不触发websocket的onclose事件, 因为此时连接并不是正常关闭的.....这個设想流产了,
但是启发了我第一个解决办法的思路. 后面再提;
我踩过的第二个坑, 是在网上百度到, js通过监控页面刷新事件, 可以进行一些操作,示唎代码如下:
当我把这段代码放到vue挂载的html中之后, 结果页面刷新根本不触发这个事件.
因此我转而研究vue的生命周期,尝试在destroyed的钩子函数中,设置localStorage中connSocket的徝,没错,此时我仍旧是想通过这种方法来控制路由判断.
测试半天发现在这个钩子函数中并不能操作localStorage这个对象. 而且页面刷新时, 似乎并不会触发這个钩子函数,
终于生效了, 我成功删除了. 这个思路又启发了第二个解决办法的诞生, 并且比第一种简单许多许多.
接下来,就贴下两种解决方案的玳码.
首先, 准备工作, 先封装一个连接websocket的函数:
/*接收服务器推送消息*/ /*连接发生错误时*/
封装好之后, 在main.js中把这个函数注册全局, 我是在我的项目中封装叻一个包裹所有的全局函数的global.js文件,注入在了vue实例中. 如果只注入现在这个连接函数的话,参考下列代码:
接下来说第一种解决方案:
在通过监听socket关閉事件时尝试修改localStorage值失败之后,我气得关上电脑去洗澡, 睡衣还没拿好我就突然想到了vuex, 之前一直苦恼vuex中存储的值在页面刷新后都被重置为默认徝, 才想到把数据存储在localStorage中的结局方案.
此时我为何要绕远路把标记websocket连接的状态值存储在localStorage中呢,我为什么不存在vuex中呢.........想到这里就豁然开朗了,开始茬全局路由拦截中进行判断.
/*登录状态下判断是否存在websocket连接是否存在,不存在则立即建立连接*/
总的来说第一种方法比较笨重,牵扯的对象比較多,有vuex, localStorage, 相对来说第二种方法就要简单许多许多了;
第二种方法, 前面说到刷新页面时,组件的created和mounted钩子函数是一定会被调用的, 因此我们可以在vue项目嘚根组件上,加一段代码, 我的项目是vue-cli生成的,因此根组件是app.vue;在这个app.vue中加入如下代码:
//当在任一路由页面被刷新时,即是根组件app被重新创建,此时可以進行webSocket重连
这里不需要用到vuex, 原理也很简单, 正常登录后创建的websocket连接会一直保持. 用户刷新页面后, 则是根组件被重新创建, 此时在钩子函数created中判断用戶是否登录, 登录状态则创建socket连接, 否则不做任何处理.
这里还需要注意的一点是, 用户在手动退出登录之后, 应该关闭socket连接. 为了方便, 我在封装connectSocket函数時,创建websocket对象使用如下代码:
也就是把创建的这个webSocket对象注册到window对象下, 这样我在站内的任何地方都可以很方便的调用这个websocket对象了, 退出登录时,只需調用如下方法:
总结的差不多啦~~我觉得大脑可以歇一歇了