vue socketio,vue web socket
主要介绍vue-socket.io的教程和踩坑的记录,通过示例代码介绍的非常详细,有一定的参考价值,感兴趣的朋友可以参考一下。
目录
前言我遇到的问题是使用教程安装与介绍(main.js)和使用(Page.vue)结合connect事件存储路由卫士的解决方案拦截的。请允许我先吐槽一句:vue-socket.io相关的中文博客太少了,所以来来去去的也就那么几个。教程比较分散,版本也比较老。即使我进行了激烈的搜索,也无法找到解决问题的方法。然后我就火了,开始看源代码,写测试demo,差不多看完了所有相关的问题。折腾了1天,我终于。做完了,下面总结一下~
考虑到很多小伙伴看完文章后还是很迷茫或者无法重现方案,所以用了一天时间附上一份https://github.com/dreamsqin/demo-vue-socket.io的demo源代码~给我一个开始吧~如果满意~谢谢
前言
Vue-socket.io实际上是基于socket.io-client的一层封装,Vue实例上挂载了$socket。同时,通过使用sockets对象可以轻松实现基于组件的事件监控,更加方便您在vue项目中使用。我目前用的是vue-socket.io:3.0.7,在它的package.json里可以看到它依赖socket.io-client:2.1.1。
我遇到的问题
websocket连接地址是从后端动态获取的,所以加载页面时还没有创建vueSocketIO实例,通过这个订阅页面时会报错。$socket.emit同时找不到Vue实例的sockets对象(里面写的事件不会被监控,即使后来连接成功)。
如果你的websocket连接地址是静态的(写死了),可以直接看教程。如果你和我有同样的问题,跳到解决方案。
控制台报告了以下错误:
使用教程
让我们抛开可能出现的问题,跟随官网的教程:
安装
安装vue-socket.io - save
引入(main.js)
从“vue”导入Vue
从导入存储。/商店
从导入应用程序。/App.vue
从“vue-socket.io”导入VueSocketIO
Vue.use(新的VueSocketIO({
debug: true,
连接:“http://metinseylan.com:1992”,
vuex: {
店,
actionPrefix: SOCKET_ ,
变异前缀:“套接字_”
},
选项:{ path:/my-app/ }//可选选项
}))
新Vue({
路由器,
店,
render: h=h(App)
}).$ mount(“# app”)
调试:生产环境建议关闭,开发环境可以打开,这样可以在控制台看到一些关于socket连接和事件监控的信息,比如如下:
连接:连接地址前缀,注意!这里只有前缀。我之前被坑过,因为明明后端已经把上下文还给我了,却莫名其妙的被移除了。vue-socket.io这里用的是socket.io-client的Manager api,关键源代码如下(只看我写中文备注的部分):
vue-socket.io(索引. js)
从“socket.io-client”导入socket io;
导出默认类VueSocketIO {
/**
*让我们利用所有资源
* @param io
* @param vuex
* @param调试
* @param选项
*/
构造函数({连接,vuex,调试,选项}){
Logger.debug=debug
this.io=this.connect(连接,选项);//获取设置的参数后调用connect方法。
this . useconnectionnamespace=(options选项. useconnectionnamespace);
this.namespaceName=(options选项. namespace name);
this.emitter=新发射器(vuex);
this.listener=新监听器(this.io,this . emitter);
}
/**
*注册SocketIO实例
* @param连接
* @param选项
*/
连接(连接,选项){
if(连接的连接类型===object) {
logger . info(` received socket . io-client instance `);
返回连接;
} else if(连接类型===string) {
const io=SocketIO(连接,选项);//实际使用的是socket.io-client的管理器API
logger . info(` n接收的连接字符串`);
返回(这个。io=io);
}否则{
引发新错误("不支持的连接类型");
}
}
socket.io-client(index.js)
var url=require( ./URL’);
函数查找(uri,opts) {
if (typeof uri===object) {
opts=uri
uri=未定义;
}
opts=opts { };
var parsed=URL(uri);//通过url.js对关系前缀进行截取
var source=parsed.source
var id=parsed.id
var path=parsed.path
var sameNamespace=cache[id]中的缓存[id]路径nsps。
var新连接=opts。强制新建 选项[强制新连接]
false===opts。多路复用 相同的命名空间;
var io
if (newConnection) {
调试("忽略%s的套接字缓存",源);
io=Manager(source,opts);
}否则{
如果(!缓存[id]) {
调试(为%s新建超正析象管实例,来源);
cache[id]=Manager(source,opts);
}
io=缓存[id];
}
if (parsed.query!opts.query) {
opts。查询=已解析。查询;
}
返回io.socket(parsed.path,opts);//实际调用的是解析后的前缀地址
}
选项。路径:这里就可以填求转发到连接地址的后缀,如果不填会被默认添加/socket.io,关键源码如下(只看我写中文备注的部分就好):
其他的选择配置可以参见https://socket.io/docs/client-api/
socket.io-client(manager.js)
函数管理器(uri,opts) {
如果(!(经理的)的这个实例返回新的Manager(uri,opts);
if (uri (object===typeof uri)) {
opts=uri
uri=未定义;
}
opts=opts { };
opts。path=opts。path /socket。io’;//看到没有,如果你不传递选项。路径参数的话会被默认安一个尾巴/socket.io
这个。nsps={ };
这个。subs=[];
this.opts=opts
这个。重新连接(opts。重新连接!==假);
这个。重新连接尝试(选择。reconnectionattempts Infinity);
这个。重新连接延迟(选项。重新连接延迟 1000);
这个。reconnecondelaymax(opts。reconnecondelaymax 5000);
这个。随机化因子(opts。随机化因子 0.5);
this.backoff=new Backoff({
min: this.reconnectionDelay(),
max: this.reconnectionDelayMax(),
抖动:这个。随机化因子()
});
这个。超时(null==opts。暂停?20000年:opts。暂停);
this.readyState=已关闭
this.uri=uri
这个。正在连接=[];
this.lastPing=null
this.encoding=false
这个。数据包缓冲区=[];
var _ parser=opts。解析器 解析器;
this.encoder=new _parser .编码器();
this.decoder=new _parser .解码器();
这个。autoconnect=opts。自动连接!==假;
如果(这个。自动连接)这个。open();
}
vuex:配置后可以在商店。射流研究…的突变或者行动监听到vue-套接字。超正析象管事件(例如:连接、断开、重新连接等),这部分目前用得比较少,也挺简单,如果有疑问可以给我留言我再单独提供教程。
使用(Page.vue)
注意:熟悉插座。碘客户端的应该知道,默认情况下,websocket在创建实例的时候就会自动发起连接了,所以切记不要在组件中重复发起连接。如果你想自己控制发起连接的时机可以将选项。自动连接设置为错误。
导出默认值{
名称:页面,
套接字:{//通过某视频剪辑软件实例对象套接字实现组件中的事件监听
connect: function () {//套接字的连接事件
console.log("从页面连接的套接字")
},
STREAM_STATUS(data) {//后端按主题名推送的消息数据
console.log(Page: data )
}
},
已安装(){
console.log(页面装载)
这个. socket.emit(STREAM_STATUS ,{ subscribe: true })//在页面加载时发起订阅,"流状态"是你跟后端约定好的主题名
}
}
事件除了在套接字对象中默认监听,你还可以在外部单独注册事件监听或取消注册:
this.sockets.subscribe(事件名称,(数据)={
这个。msg=数据。消息;
});
这个。插座。取消订阅(事件名称).
但这种方式从源码上看是不支持参数传递的,只支持传递事件名及回调函数(部分源码如下):
vue-Socket.io(mixin.js)
创建之前(){
如果(!这个。插座)这个。套接字={ };
如果(键入此. vueSocketIo===object) {
for(const对象。键的命名空间(这个.$vueSocketIo)) {
这个。插座[名称空间]={
订阅:(事件,回调)={
这个. vueSocketIo[命名空间]。发射器。添加监听器(事件、回调、this);
},
取消订阅:(事件)={
这个. vueSocketIo[命名空间]。发射器。移除监听器(事件,this);
}
}
}
}否则{
这个10.99美元vuesocketio。发射器。添加监听程序(事件、回调、这个);
这个10.99美元vuesocketio。发射器。移除监听器(事件,this);
}
}
解决方案
针对我上面描述的问题,最大原因就在于获取窝连接地址是异步请求,如文章开头的截图,页面安装打印时,这个。$套接字还是未定义。所以我们要做的就是怎么样让页面加载在VueSocketIO实例创建之后。
我提供两种解决方案,具体怎么选择看你们的需求~
保证拿到窝连接地址后再将某视频剪辑软件实例挂载到应用
缺点:如果你获取窝地址的请求失败了,整个项目的页面都加载不出来(一般服务器出现问题才会有这种情况产生)
优点:实现简单,一小段代码挪个位置就好
主页。射流研究…
从“vue”导入某视频剪辑软件
从导入应用程序 App.vue
从导入路由器。/路由器
从导入存储。/商店
从" @/api/Parent "导入ParentApi
从" vue-socket.io "导入VueSocketIO
/* 使用vue-socket.io */
ParentApi.getSocketUrl().然后((res)={
Vue.use(新的VueSocketIO({
调试:假,
连接:res.data.path,
选项:{ path: /my-project/socket.io }
}))
新Vue({
路由器,
店,
render: h=h(App)
}).$ mount("# app ")
})
控制台打印如下图:
结合connect事件+store+路由守卫实现拦截
原理:异步请求回调中创建VueSocketIO实例并监听连接事件,监听回调中修改isSuccessConnect参数的值,在页页面路由中增加输入前守卫,利用设置间隔周期性判断isSuccessConnect的值,满足条件则取消定时执行并路由跳转。
缺点:实现起来稍微复杂一点
优点:不会影响其他页面的加载
主页。射流研究…
从“vue”导入某视频剪辑软件
从导入应用程序 App.vue
从导入路由器。/路由器
从导入存储。/商店
从" @/api/Parent "导入ParentApi
从" vue-socket.io "导入VueSocketIO
ParentApi.getSocketUrl().然后((res)={
let vueSocketIo=new vueSocketIo({
调试:假,
连接:res.data.path,
选项:{ path: /my-project/socket.io }
})
//监听连接事件,设置isSuccessConnect为真实的
vueSocketIo.io.on(connect ,()={
console.log(从主页. js进行套接字连接)
商店。提交( newIsSuccessConnect ,true)
})
Vue.use(vueSocketIo)
})
新Vue({
路由器,
店,
render: h=h(App)
}).$ mount("# app ")
商店。射流研究…
从“vue”导入某视频剪辑软件
从" vuex "导入状态管理
Vue.use(Vuex)
导出默认的新Vuex .商店({
状态:{
//套接字连接状态
isSuccessConnect: false
},
突变:{
newIsSuccessConnect(状态,值){
state.isSuccessConnect=value
}
},
getters: {
getIsSuccessConnect: state={
返回state.isSuccessConnect
}
},
动作:{
}
})
router.js
从“vue”导入某视频剪辑软件
从“vue路由器"导入路由器
从导入存储。/商店
Vue.use(路由器)
导出默认新路由器({
模式:"历史",
base: process.env.BASE_URL,
路线:[
{
路径:"/page ",
名称:页面,
component:()=import(/* webpackChunkName: Page */ ./页/页。vue’),
输入前:(收件人,发件人,下一个)={
设intervalId=setInterval(()={
//直到商店中isSuccessConnect为真实的时才能进入/页面
if(store . getters . getissuccessconnect){
间隙(有效间隔)
下一个()
}
}, 500)
}
}
]
})
控制台打印出下图:
参考资料:
1、vue插座。io:https://github.com/MetinSeylan/Vue-Socket.io
2、socket.io客户端:https://github.com/socketio/socket.io-client
3.vue-路由器卫士:https://router . vue js . org/zh/guide/advanced/navigation-guards . html
关于vue-socket.io使用教程详解和踩坑记录的文章到此结束。更多关于vue-socket.io使用教程的信息,请搜索我们之前的文章或者继续浏览下面的相关文章。希望大家以后能多多支持我们!
郑重声明:本文由网友发布,不代表盛行IT的观点,版权归原作者所有,仅为传播更多信息之目的,如有侵权请联系,我们将第一时间修改或删除,多谢。