Vue uses Vue-socket.io to implement instant chat application (vuex management)

PS: Dynamic address issues, automatic connection issues, vuex management, learning suggestions 

1. Dynamic socket address problem

Recently, a small partner asked a question about the dynamic address in a private message. Today, I will give a unified answer and talk about my understanding.

The so-called dynamic address is to request the back-end interface, return an address, and then you connect to the socket.io server. For example:

Basic data server.json:

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

As above, I defined a basic JSON data with a server address in it. Next, we request this JSON file through axios to simulate the data returned by the backend. 

Get socket service address getSocketServer.js

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

 Directly return a promise object. In this case, how to obtain this dynamic address?

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,
      })
  )
});

 In this way, the backend path can be obtained dynamically and the socket server can be connected.

2. Automatic connection problem

The current socket connection is written directly in main.js. When we start the vue project, it will automatically connect to the socket server, which is obviously not allowed in the actual project. (The user does not log in to the system, enters the account password, and connects to the socket service, which is obviously a waste of resources.)

So, how do we connect manually (connect when we need to?)

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

Add configuration items: options: {autoConnect:false} //Indicates that automatic connection is turned off

 Usually, we must have a login page on the front end:

 

 We only need to manually connect to the server after the user enters the user name. (After the connection, we can add the user name to the socket object attribute in combination with what I said in the previous article, so that we can privately chat and process information)

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

Bind the login event directly to the login button, and use this.$socket.connect() to manually connect! (You can also perform operations such as validation on user input)

 

3. socket.io managed by vuex

Ok, here comes the main content of today: vuex manages socket.io.

3.1 vuex management model diagram

Through this illustration, we can understand the role of vuex in socket communication, as long as it is responsible for listening to the events published by the socket, and then calls it for multiple components. Because vuex is the state management warehouse of vue, it can realize the communication between any components.

To illustrate with an example:

Now there is a user 'Tom' who wants to send you a private message, the server must issue an event: socket.emit('chatPrivate'); 

There is a chat component: chat.vue

There is also a home page component: first.vue

(If you are in the chat component, you can listen to this event. What if you are not there? It should be a prompt from the homepage: 'Someone sent you a message!'. At this time, you have to listen to this event in the homepage component to receive it message. You wrote the same listener event twice)

What will happen if you use vuex management?

Vuex is responsible for listening to this message, and when it receives the message, it assigns it to its own variable => state.xxx;

Others who also need this message can directly monitor the change of the variable state.xxx.

3.2 Native sockets monitoring implementation

 How? Below is our code description. In order to show you the difference between the two intuitively, I will show both situations:

Here are two simple components: first, chat; the welcome event we simply listen to:

//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 implementation 

The component listens to socket events, but the same code is written twice. Below we use vuex to monitor:

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
  })
);

 Introduce the store file and add configuration items in VueSocketIo. Among them, Prefix is ​​a prefix, which means that when you define a vuex function, you can distinguish between ordinary functions and socket functions according to the prefix. (Here we still turn on automatic connection)

We define simple vuex file (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: {}
})

 Run the project:

Vuex has received events from the server.

 

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

<script>
export default {
}
</script>

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

In this way, in our first and chat components, no events are monitored, and parameters are received through vuex:

Rewrite the code:

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

For the rest, we can directly monitor the changes of msg! (How to process the returned data depends on your actual business scenario)

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

 The result is as follows:

 Note: We use the prefix to define the event SOCKET_welcome in vuex, and write welcome directly on the server side. The backend can recognize events prefixed with SOCKET_.

Service-Terminal:


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

Through the above two examples, you can clearly see the role of vuex in socket applications. As the communication messenger of multiple components, vuex is responsible for listening to socket server events, and others listen to the state variable of vuex.

 3.2 Why not publish events with vuex?

 Some people may wonder, why does vuex management only monitor and not publish? That is, vuex acts as an intermediate role, which can not only monitor events, but also publish events. If vue components want to communicate with the server, they only need to monitor vuex state data and commit() veux events. As shown below

 To answer this question, we need to understand your business scenario clearly.

1. Send data to the socket server, maybe the data in the two places are the same? (Publish event: emit can actually be understood as sending data to the server) For example, chat.vue sends actual chat information; may you also send the same data in first.vue?

The parameters of the emit (Event, Params) event are special and not shared by all components, so there is no need to put the release event into vuex for management;

2. We publish events through this.$socket.emit(), can this statement be used in vuex?

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

 We listen to a test event;

Defined in vuex:

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

 In the chat.vue component, bind an event to a button:

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

The result is as follows:

 This.$socket.emit() is not recognized in vuex.

 3.3 How to deal with vuex.state

 If there is a real need, say that the component release event is monitored, and the content of other components needs to be modified, you can use separate writing, which is also clearer.

 for example:

chat.vue is a component dedicated to chatting, and first.vue is a home page component. When someone sends you a message, several unread messages should be displayed on the home page. When you go to the chat component to process, the unread messages on the home page need to be updated.

 

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

The vue component publishes the event, the socket listens and publishes the event, and the vuex listens, modifies the state data, and causes changes in other components.

Of course, this is just a simple example, and there must be a better solution; I just want to show that the communication between components and sockets is easiest to use this.$socket.emit().

 This example can be solved with the callback of emit(), which is the simplest; Vue publishes an event, passes a callback function to it, the server handles it, executes the callback, returns the data, and then store.commit() modifies the data. As shown below:

If you are interested, you can try it out. The callback can refer to: 

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

 4. Study suggestions

For the study of socket.io, I still hope that I can type the code to understand it, instead of just reading the article. At the same time, think more about why this is so;

 

 This is an article by a blogger. Using io.sockets.sockets can return a collection of objects. Why? How did you find out? ( For this, you can read my last article. I am not saying who is good and who is bad. I just remind everyone to think more, try more, and understand the principles of the underlying framework. )

What is done on paper is superficial in the end, and I know that this matter must be done!

(Maybe there are mistakes in my own understanding, welcome to leave a message to correct me, update the actual combat project of vue-socket.io in the next issue, make a chat room, and finish talking about the actual combat project, this knowledge point will be over)

From connection, communication, management, and actual combat, it involves the entire life cycle of vue-socket.io, and I hope it will be helpful to everyone. 

Guess you like

Origin blog.csdn.net/weixin_47746452/article/details/121330186