571
社区成员
发帖
与我相关
我的任务
分享本聊天室使用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,
});
});
