基于vue+express+socket.io的简易多人聊天室

瑞脑销金兽 2022-01-17 11:19:09

一. 项目概述

     本聊天室使用vue和Element UI框架开发项目前端,使用express作为后端和前端短连接的框架,使用socket.io建立前端和后端的长连接通信。

     1. Vue

      Vue 是一套用于构建用户界面的渐进式框架。Vue 的核心库只关注视图层,不仅易于上手,还便于与第三方库或既有项目整合。

      2. Element UI

      elementUI是基于vue实现的一套不依赖业务的UI组件库,提供了丰富的PC端组件,减少用户对常用组件的封装,降低了开发的难易程度。

      3. Express

       Express 是流行的 Node框架它提供了以下机制:

       为不同 URL 路径中使用不同 HTTP 动词的请求(路由)编写处理程序。

       集成了“视图”渲染引擎,以便通过将数据插入模板来生成响应。

       设置常见 web 应用设置,比如用于连接的端口,以及渲染响应模板的位置。

       在请求处理管道的任何位置添加额外的请求处理“中间件”。

      4. Socket.io

       Socket.IO是一个完全由JavaScript实现、基于Node.js、支持WebSocket的协议用于实时通信、跨平台的开源框架,它包括了客户端的JavaScript和服务器端的Node.js.

二. 项目设计及实现

  • 登录

    用户在登录界面输入用户名即可登录,同一个用户可以多次登录,且登录后都表示同一个用户,用户输入用户名密码后触发socket.io的login事件,传递登录信息,后端监听login后向所有用户广播当前登录用户列表和用户人数信息。

前端:

login() {
      this.initConnection()
      this.$router.push({
        name: "chat",
        params: {
          username: this.name,
        },
      });
    },
    initConnection() {
      let userInfo = {
        userId: Date.now(),
        username: this.name,
      };
      this.$socket.emit("login", userInfo);
    },
  },

后端:

socket.on('login', function (obj) {
    socket.name = obj.username
    let hasLogin = onlineUsers.filter((user) => {
      return user.username == obj.username;
    })
    if (hasLogin.length == 0) {
      onlineUsers.push(obj)
      onlineCount++;
      socket.emit('login', {
        onlineUsers: onlineUsers,
        onlineCount: onlineCount,
        user: obj,
      });
      socket.broadcast.emit('login', {
        onlineUsers: onlineUsers,
        onlineCount: onlineCount,
        user: obj,
      });
	  socket.broadcast.emit('otherslogin', {
        user: obj,
      });
    }
    console.log(obj.username + '加入了聊天室');
  }

 

  •  维护用户列表和用户数

    用户登录后会根据登录时后端传输的在线用户列表和人数渲染前端,同时前端会和后端socket.io建立长连接,订阅登录事件,以便实时维护在线用户列表和人数。其他用户登录后以登陆的用户顶端会有一个短暂的弹窗提示其他刚登陆的用户。

this.sockets.subscribe("login", (data) => {
      let ul = [] 
      ul.push({username:this.userInfo})
      for(var i in data.onlineUsers){
        if(data.onlineUsers[i].username != this.userInfo){
            ul.push(data.onlineUsers[i])
        }
      }
      this.userList = ul;
      this.number = data.onlineCount;
    });
    this.sockets.subscribe("otherslogin", (data)=>{
      this.$message(data.user.username + ' 加入聊天室')
})

 

  • 聊天记录实时更新

      用户登录后使用axios异步获取后端当前的聊天记录。保存在本地用户每发送一条消息都向后端发送,后端向所有登录的其他用户广播此消息,用户收到消息后将其渲染到前端,同时为了区分消息是否是自己发送,渲染消息页面时判断消息的用户名和自己是否相同,自己发送的显示在右边,其他人发送的显示在左边

//异步获取聊天记录  
created(){
    let _this = this
    axios.get('http://localhost:3001/getHistory').then(function(res){
      _this.msgList = res.data.msgList
      _this.$store.state.store_msg_list = res.data.msgList
    }).catch(function(err){
      console.log(err)
    })
},

//前端发送消息的方法 
submitMessage() {
      let msg = {
        username:this.userInfo,
        time:Date.now(),
        msg:this.message,
      }
      
      this.msgList.push(msg)
      this.$socket.emit("message", msg);
      this.message = ""
}

//前端订阅message事件
this.sockets.subscribe("message", (data) => {
      this.msgList.push(data)
});

//聊天记录渲染
<el-main class="main-container">
  <div class="div1">
    <p
      :class="{ right: msg.username == userInfo }"
      v-for="(msg, index) in msgList"
      :key="index"
    > 
      <span class="name" v-if="msg.username != userInfo" >{{msg.username}}</span>
      <span class="name" v-else style="float:right;">{{msg.username}}</span>
      <span class="content">{{ msg.msg }}</span>
    </p>
  </div>
</el-main>

 

 

  • 登出

      用户点击推出后后端在线用户列表删除此人,同时在线人数减一,向其他用户广播数据

logout() {
      this.$socket.emit("logout", this.userInfo);
      this.$router.push({
        name: "home",
      });
}

 后端:

 socket.on('disconnect', function () {
    console.log(socket.name + '退出了聊天室');
    onlineUsers.forEach(function (item, index, arr) {
      if (item.username == socket.name) {
        arr.splice(index, 1)
        onlineCount--;
      }
    })  
    io.emit('logout', {
      onlineUsers: onlineUsers,
      onlineCount: onlineCount,
    });
  });

 作者:NP361

 

...全文
635 回复 打赏 收藏 转发到动态 举报
写回复
用AI写文章
回复
切换为时间正序
请发表友善的回复…
发表回复

571

社区成员

发帖
与我相关
我的任务
社区描述
软件工程教学新范式,强化专项技能训练+基于项目的学习PBL。Git仓库:https://gitee.com/mengning997/se
软件工程 高校
社区管理员
  • 码农孟宁
加入社区
  • 近7日
  • 近30日
  • 至今

试试用AI创作助手写篇文章吧