Vue 使用 Vue-socket.io 实现即时聊天应用(vuex管理)

PS:动态地址问题、自动连接问题、vuex管理、学习建议 

1. 动态socket地址问题

最近有小伙伴私信问动态地址问题,今天统一做一下答复,谈谈自己的理解。

所谓动态地址,就是请求后端接口,返回一个地址,然后你再连接这个socket.io服务器。如下示例:

基础数据 server.json:

{
    "server":"http://localhost:9000"
}

如上,我定义了一个基础JSON数据,里面有一个服务器地址,下面我们通过axios请求这个JSON文件,模拟后端返回数据。 

获取socket服务地址 getSocketServer.js

import axios from 'axios'
export const server = axios.get('./server.json');

 直接返回一个promise对象,这种情况下,如何获取这个动态地址呢?

main.js:

import VueSocketIO from "vue-socket.io";
import {server} from './getSocketServer'

server.then(res=>{
  Vue.use(
      new VueSocketIO({
        debug: true, // debug调试,生产建议关闭
        connection: res.data.server,
      })
  )
});

 这样即可实现动态获取后端路径,进行socket服务器的连接了。

2. 自动连接问题

目前的socket连接,都是直接写在main.js中的,当我们启动vue项目的时候,就自动连接上了socket服务器,这显然在实际的项目中是不允许的。(用户都没有登录系统,输入账号密码,就连接了socket服务,显然是浪费资源的。)

那么,我们如何手动连接(在我们需要连接的时候连接呢?)

// 注册并使用Vue-socket.io
Vue.use(
  new VueSocketIO({
    debug: true, // debug调试,生产建议关闭
    connection: 'http://localhost:9000',
    options: {     //Optional options, 
        autoConnect:false, 
//autoConnect 通常与 this.$socket.connect()结合使用,表示手动连接socket服务器
    }
  })
);

添加配置项:options:{autoConnect:false}        //表示关闭自动连接

 通常,我们前端必有登录页面:

 

 我们只需要在用户输入了用户名之后,手动连接到服务器即可,(连接之后,可以结合我上篇文章说的,将用户名添加到socket对象属性上,便于我们私聊处理信息)

/* 登录 */
    login(){
      this.$socket.connect();
    },

直接给登录按钮绑定login事件,使用this.$socket.connect()手动连接即可!(你还可以对用户输入做校验等操作)

 

3. vuex管理的socket.io

好的,来到了今天的主要内容:vuex管理socket.io。

3.1 vuex管理模型图

我们可以通过该图示,理解vuex在socket通信中的作用,只要是负责监听socket发布的事件,然后供多组件调用。因为vuex是vue的状态管理仓库,可以实现任意组件间的通信。

举个例子说明:

现在有一个用户 ‘Tom’,想给你发私信,服务器肯定是发布事件:socket.emit('chatPrivate'); 

有一个聊天组件:chat.vue

还有一个主页组件:first.vue

(如果你在聊天组件,可以监听这个事件,如果你不在呢?应该是主页给出提示:‘有人给你发消息了!’。这个时候,你要在首页组件也监听这个事件,才能收到消息。那同一个监听事件,你写了两次)

如果使用vuex管理,会是怎样?

vuex负责监听这个消息,收到消息了,就赋值给自己的变量=>state.xxx;

其他也需要这个消息的,直接监听state.xxx这个变量的变化即可。

3.2 原生sockets监听实现

 如何实现呢?下面我们代码说明,为了给大家直观看出两者的区别,我将两种情况都展示出来:

这是两个简单的组件:first、chat;我们简单监听的welcome事件:

//first.vue:
<script>
export default {
 sockets:{
    welcome:function(data){
      console.log(data)
    },
  },
}
</script>

//chat.vue:
<script>
export default {
 sockets:{
    welcome:function(data){
      console.log(data)
    },
  },
}
</script>

 

3.3 vuex实现 

实现了组件监听socket事件,但是一样的代码,写了两遍。下面我们用vuex监听:

import Vue from "vue";
import App from "./App.vue";
import store from './store/index'
import VueSocketIO from "vue-socket.io";

Vue.config.productionTip = false;
 // 注册并使用Vue-socket.io
Vue.use(
  new VueSocketIO({
    debug: false, // debug调试,生产建议关闭
    connection: "http://localhost:9000",
    vuex: {
      store,
      actionPrefix: 'SOCKET_',
      mutationPrefix: 'SOCKET_'
    },
    // options: { autoConnect:false, } //Optional options
  })
);

 引入store文件,在VueSocketIo中添加配置项即可。其中,Prefix是前缀,表示你在定义vuex函数的时候,根据前缀区分普通函数还是socket函数。(这里我们还是打开自动连接)

我们定义简单的vuex文件(index.js)

import Vue from 'vue'
import Vuex from 'vuex'

Vue.use(Vuex)

export default new Vuex.Store({
    state: {
    },
    mutations: {
        /* 监听服务器事件,直接使用SOCKET_'服务器发布的时间名即可。' */
        SOCKET_welcome(state,data){
            console.log('vuex-welcome:',data);
        },
    },
    actions: {},
    modules: {}
})

 运行项目:

vuex已经接收到服务器的事件了。

 

<template>
  <div>
      first.vue
  </div>
</template>

<script>
export default {
}
</script>

<style scoped>
div{
    padding: 10px;
    background-color: antiquewhite;
}
</style>

这样,我们first与chat组件里,什么事件都没有监听,通过vuex来接收参数:

改写代码:

state: {
        msg:'',
    },
    mutations: {
        /* 监听服务器事件,直接使用SOCKET_'服务器发布的时间名即可。' */
        SOCKET_welcome(state,data){
            console.log('vuex-welcome:',data);
            state.msg=data;
        },
    },

剩下的事,我们直接监听msg的变化即可!(具体怎么处理返回的数据,就看你实际的业务场景啦)

 computed:{
        msg(){
           return store.state.msg 
        }
    },

 结果如下:

 注意事项:我们在vuex中使用前缀定义事件 SOCKET_welcome,在服务器端直接写welcome即可。后端能识别SOCKET_前缀的事件。

服务器端:


io.on('connection', function(socket){
  console.log('用户已连接');
  /* 发布自定义事件 */
  socket.emit('welcome','欢迎连接socket.');
  /* 每一个socket都会监听一个特殊函数:disconnect  关闭连接 */
  socket.on('disconnect',()=>{
    console.log('用户关闭了连接');
  });
});

通过上面两个示例,可以清楚看到vuex在socket应用中的作用。作为多个组件的通信的使者,vuex取负责监听socket服务器的事件,其他人监听vuex的state变量。

 3.2 为什么不用vuex发布事件?

 或许有人会疑惑,vuex管理,为何只监听,不发布呢?就是vuex充当所有中间角色,既能监听事件,也能发布事件,vue组件想要和服务器通信,只要监听vuex  state数据和commit()veux事件即可。如下图

 想要解答这个问题,我们要了解清楚你的业务场景了。

1. 给socket服务器发送数据,可能两个地方的数据相同嘛?(发布事件:emit 其实可以理解为给服务器发送数据)比如chat.vue,发送实际的聊天信息;你可能在first.vue中也发送相同的数据吗?

emit(Event,Params)事件的参数具有特殊性,不具备所有组件都共享,所以不需要将发布事件也放到vuex中管理;

2. 我们通过 this.$socket.emit() 发布事件,这个语句能在vuex中使用吗?

/* 监听事件 */
socket.on('test',data=>{
    console.log('test',data)
});

 我们监听一个测试事件;

在vuex中定义:

mutations: {
        /* 监听服务器事件,直接使用SOCKET_'服务器发布的时间名即可。' */
        SOCKET_welcome(state,data){
            console.log('vuex-welcome:',data);
            state.msg=data;
        },
        /* 测试发布事件 */
        vuexEmit(state,data){
            this.$socket.emit('test','vuextest');
        },
    },

 chat.vue组件中,给一个按钮绑定事件:

methods: {
        test(){
            store.commit('vuexEmit');
        }
    },

结果如下:

 在vuex中是无法识别this.$socket.emit()。

 3.3 如何处理 vuex.state

 如果真的有需求,说组件发布事件被监听了,需要修改其他组件的内容,你可以使用分开的写法,也比较清晰。

 举个例子:

chat.vue是专门处理聊天的组件,而first.vue是首页组件。有人给你发送消息,首页要显示几条未读。当你到chat组件处理后,首页的未读消息要更新。

 

vue=>socket;socket=>vuex;vuex=>vue

vue组件发布事件,socket监听后发布事件,vuex监听,修改state数据,引起其他组件的变化。

当然,这只是一个简单的例子,肯定有更好的解决办法;我只是想说明,组件与socket的通信,使用 this.$socket.emit()是最简单的。

 这个例子可以使用emit()的回调解决是最简单的;vue发布事件,传一个回调函数过去,服务器处理好了,执行回调,返回数据,再store.commit()修改数据。如下图:

有兴趣的可以尝试一下,回调可以参考: 

 https://socket.io/docs/v4/emitting-events/

 4. 学习建议

对于socket.io的学习,还是希望能自己敲代码去理解,而不是看了文章就算了。同时,多思考为什么是这样;

 

 这个是某博主的文章,使用io.sockets.sockets就能返回对象集合,为什么呢?你是怎么发现的呢?(关于这个,可以看看我上一篇文章,我不是说谁好谁坏,只是提醒大家,多思考,多尝试,多了解底层框架的原理。

纸上得来终觉浅,绝知此事要躬行!

(可能自己理解也有错误,欢迎留言指正,下期更新vue-socket.io的实战项目,做一个聊天室,讲完实战项目,这个知识点就结束啦)

从连接、通信、管理、实战,涉及了vue-socket.io 使用的全生命周期,望对大家有帮助。 

  • 15
    点赞
  • 27
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
Vue2使用vue-socket.io可以实现Socket.io的集成,实现实时聊天等功能。首先,需要在项目中引入vue-socket.io扩展,可以通过npm安装vue-socket.io并引入。 在Vue实例中,使用Vue.use()来注册并使用Vue-socket.io。在注册时,需要传入相应的配置参数,包括debug、connection、vuex等。其中,debug用于调试,可以选择关闭;connection用于指定Socket.io的连接地址;vuex用于在Vuex使用Socket.io的事件监听。 具体实现步骤如下: 1. 首先,安装vue-socket.io扩展:npm install vue-socket.io 2. 在Vue实例中引入VueVueSocketIO,并配置相应的参数。 3. 创建Vuex store,并在配置参数中指定vuex为store的实例。 4. 在Vue实例中使用Vue.use()注册Vue-socket.io,并传入配置参数。 这样,Vue2就可以使用vue-socket.io扩展来实现Socket.io的集成了。可以使用Vue-socket.io提供的方法来监听Socket事件,并实现相应的功能。 总结一下,Vue2使用vue-socket.io扩展可以实现Socket.io的集成,通过注册Vue-socket.io并传入相应的配置参数,可以在Vue实例中实现Socket事件的监听和处理。这样就可以实现实时聊天等功能了。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* [Vue 使用 Vue-socket.io 实现即时聊天应用vuex管理)](https://blog.csdn.net/weixin_47746452/article/details/121330186)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_1"}}] [.reference_item style="max-width: 33.333333333333336%"] - *2* [vue-socket.io-extended:Vue.jsVuexSocket.io绑定(受Vue-Socket.io启发)](https://download.csdn.net/download/weixin_42160425/18170249)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_1"}}] [.reference_item style="max-width: 33.333333333333336%"] - *3* [Vue 使用 Vue-socket.io 实现即时聊天应用(实战篇 一)](https://blog.csdn.net/weixin_47746452/article/details/121359940)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_1"}}] [.reference_item style="max-width: 33.333333333333336%"] [ .reference_list ]
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值