前言
vue项目中有使用到socket
长连接,之前一直都是都是使用vue-socke.io
github地址,但最近在使用时,出了一些莫名奇妙的bug,也是为此掉了不少头发,最后还是解决了。关于socket
相关内容介绍以及使用场景,这里不会做太多介绍(主要是懒),可以翻看其他文章。本文主要介绍如何使用,以及再使用时需要注意一些什么。关于文章中使用的代码,我放上github地址。
安装
这里我们安装vue.socket.io
模块和socket.io-client
模块,也可以不用socket.io-client
模块。
1 2 3 4 5
| cnpm i vue-socket.io -S cnpm i socket.io-client -S
yarn vue-socket.io yarn i socket.io-client
|
vue 客户端使用
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44
| import Vue from 'vue' import App from './App.vue' import router from './router' import store from './store' import VueSocketIO from 'vue-socket.io' import SocketIO from "socket.io-client"
Vue.config.productionTip = false
const socketOptions = { autoConnect: false, }
Vue.use( new VueSocketIO({ debug: true , connection: SocketIO("127.0.0.1:1024", socketOptions), store, }) )
new Vue({ sockets: { connecting() { console.log('正在连接') }, disconnect() { console.log("Socket 断开"); }, connect_failed() { cosnole.log('连接失败') }, connect() { console.log('socket connected') } }, router, store, render: h => h(App) }).$mount('#app')
|
1 2 3 4 5 6 7 8
| Vue.use( new VueSocketIO({ debug: true , connection: 127.0.0.1:1024, store, }) )
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54
| <template> <div id="app"> <div id="nav"> <button @click="connect">连接socket</button> <button @click="sendMessage">发送数据</button> </div> </div> </template>
<script> export default { data() { return {
} },
methods:{
connect() {
this.$socket.open() this.sockets.subscribe('welcome', data => { console.log('welcome data ', data) }) },
sendMessage() { this.$socket.emit('hello', '这里是客户端')
}
},
sockets:{ welcome: data => { console.log('welcome data ', data) }
} } </script>
|
客户端使用总结
客户端自带监听事件
connect
:连接成功connecting
:正在连接disconnect
:断开连接connect_failed
:连接失败error
:错误发生,并且无法被其他事件类型所处理reconnect_failed
:重连失败reconnect
:成功重连reconnecting
:正在重连
监听自定义事件
1 2 3 4 5
| sockets:{ welcome: data => { console.log('welcome data', data) } }
|
1 2 3
| this.sockets.subscribe('welcome', data => { console.log('welcome', data) })
|
发送消息
注意:监听用的是this.sockets
,发送消息是this.$socket
,不要弄混。
1
| this.$socket.emit('hello', '这里是客户端')
|
关于跨域问题
socket会存在跨域问题,之前看文章又说到在vue.config.js
中配置代理,差不多和后台接口代理配置一样,但我试过好像没啥鸟用,如果有知道的同学麻烦留言告诉一声,实际项目中的解决方式还是后端配置跨域问题。
服务端使用
这里为啥要讲服务端使用,主要是为了让同学更好的体验socket,其次是为了引出后面的bug,也是一个扩展知识把,是不是觉得自己赚了😄。本地开启socket服务可以更好的进行调试。服务端主要还是使用node
,毕竟咱也不会java、python…,这里以及配置了socket跨域。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52
|
var http = require('http'); var io = require('socket.io');
var server = http.createServer(function (req, res) {
var headers = {}; headers["Access-Control-Allow-Origin"] = "*"; headers["Access-Control-Allow-Methods"] = "POST, GET, PUT, DELETE, OPTIONS"; headers["Access-Control-Allow-Credentials"] = true; headers["Access-Control-Max-Age"] = '86400'; headers["Access-Control-Allow-Headers"] = "X-Requested-With, Access-Control-Allow-Origin, X-HTTP-Method-Override, Content-Type, Authorization, Accept"; res.writeHead(200, headers); res.end(); });
server.listen(1024,function() { console.log('server runing at 127.0.0.1:1024') })
var socket = io.listen(server, {origins: '*:*'});
socket.on('connection',function(socket) { console.log('客户端有连接') socket.on('disconnect', () => { console.log('客户端断开') }) socket.emit('welcome','欢迎连接socket') socket.on('hello', data => { console.log('接收客户端发送数据', data) })
});
|
服务端总结
服务端接收和发送消息和客户端对调的,客户端emit
发送消息,那么服务端这里就要on
监听客户端发送的消息,服务的发送同理。
踩坑
订阅事件记得要取消
socket主要还是用来写聊天室,加入socket房间后要订阅房间内所有的聊天内容,这时如果没有取消之前的订阅事件,下次进入会多次订阅消息。也就是别人只发一条消息,你这边接收到的却是两条甚至多条。哪如何取消订阅呢,我的处理方式是在离开当前聊天页面后,自动取消之前所有的订阅事件。
1 2 3
| beforeDestroy() { this.sockets.unsubscribe(eventName) }
|
同理,如果是有指定页面才加入socket房间,退出页面时也要记得关闭socket连接。比如你在created
中开始连接socket,在beforeDestroy
要记得关闭socket,不然下次进入也会连接socket。
1 2 3 4 5 6 7 8
| created() { this.$socket.open() this.$socket.connected } beforeDestroy() { this.$socket.close() }
|
Type Error: this.sockets.subscribe is not a function
这是我最近遇到的问题,原本以为是自己的this指向有问题,然后从到尾查遍了整个逻辑this,发现并不是这个问题。

在打印this.sockets
之后我发现问题

subscribe
订阅事件并没有直接存在,而是某个对象的属性,于是尝试了一下this.sockets.listenner.subscribe
发现能用了。
你以为这就结束了???接着我又发现问题
1 2 3 4 5 6 7
| sockets:{
welcome: data => { console.log('welcome data ', data) }
}
|
并且订阅的事件中,socket日志显示component: undefined
没有看到数据
全局的订阅事件没有生效,并且socket自带的连接事件也没有启动打印。我直接傻了😢,之前使用的时候还没有这些问题,百度一大堆无果后,开始像官方求助。于是找到了问题。
Vue-Socket.io: #connect subscribe, component: undefined

大概的意思是说,出现问题的都是3.0.9的版本,将版本后可以解决这个问题。这也是我为啥要把socket服务端写进了的原因。自己本地写了一个小demo后,还真的是版本的问题,随后就有了这篇文章。