基于Socket.io的简易聊天室
基于Socket.io的简易聊天室
该聊天室样式写的很简易,甚至可以说low,但是咱们是研究技术的,样式不是重点 -。-
功能
- 在线人员
- 登录与退出
- 当前用户
- 实时发送消息
步骤一:首先要有个HTML页面才能展示这些内容吧,我这个聊天室使用的Vue的语法功能搭建的HTML,都是在一个HTML中写的,没有搭建成单页面应用。首先简易的把样式写了,能让我们看到这个效果就行(这里就不给大家写了,我相信大家都是会的,就不献丑了
)
步骤二:接下来才是进入正题了
-
首先,初始化整个项目:
cnpm init
在初始化的时候,记得指定入口文件为index.js, 这是我们服务端的入口文件 初始化完成后,代码中会多个package.json包-
-
第二步,我们要创建这个Index.js,用来写我们的Node服务端代码,写代码之前,我们要先安装需要的依赖插件:express、socket.io。
cnpm install express socket.io --save
依赖安装完毕后,可以正式的撸码了!!!我们先将需要用到的模块包引入进来
const express = require('express'); const app = express(); // 初始化express const http = require('http').Server(app); // 创建个Http服务器 const io = require('socket.io')(http); // 将Http服务注入到io中 const path = require('path'); // 做路径处理
首先我们先检验一下这个HTTP服务是否开启成功
http.listen(3000, function(){ console.log('服务开启成功') })
利用nodemon 来运行该index.js
验证成功,服务成功开启!接下来我们再来验证一下前端是否能够访问,这里利用express中的get方法来访问 ‘/’ 也就是根目录,调用send方法,向前端发送数据!
app.get('/', function(req, res){ res.send('Hello World') })
打开浏览器输入我们监听的端口号:localhost:3000
成功!
现在前端与后端已经成功打通,接下来就是如何让页面显示我们想要显示的样子了 -
第三步,将我们之前写好的前台HTML页面显示到浏览器中
首先要使用express中的use方法,来指定静态资源目录,这样前端访问服务端的时候才能跳转到指定目录下(由于我的前台页面放到了public目录下,所以路径为
/public
)app.use(express.static(path.join(__dirname+ '/public'))) // app使用express的一个方法指定静态资源路径为public
指定完成后,我们来修改一下之前写好的那个get方法,在之前,我们是向前台发送了一个Hello World字符串, 现在我们向前台发送整个HTML文件,利用sendFile()方法发送文件
app.get('/', function(req, res){ res.sendFile(path.join(__dirname+ '/public/index.html')) // 将该路径发送到请求的地址中 })
将该页面发送到前台后,再次打开localhost:3000,就可以看到你之前写好的HTML页面了。
-
第4步,我们来写一下前台的HTML逻辑
打开HTML, 首页肯定是要有一个输入框,一个登录按钮。由于我们使用的是Vue语法,所以我们要进行双向绑定一下这个输入框的值,在data中创建相对应的值
logBol:是我们用来判断是否登录了,用来显示和隐藏登录页面的值
user则是用户登录时存储的数据,其中uId为用户登录成功后,我们为用户随机生成的一个用户ID,这些创建完毕后,我们就开始写登录事件
首先要判断需要输入有效值,再随机生成userId,生成ID之后,就可以调用initSocket初始化方法。// 生成用户Id genUid(){ // 时间戳 + 随机数 return `fc_${new Date().getTime() + ''}${Math.floor(Math.random()*89900)}` }
在初始化函数initSocket中,首先要建立socket的链接,随后可以向后台发送login登录事件,同时将当前用户登录的信息传递给后台
接下来就是后台要监听前台发送来的事件,在index.js
中建立监听
当前台点击了登录之后,后台就可以监听到这个登录了,同时能够拿到前台发来的用户数据,res则为前台传来的用户数据,接收到后,我们可以将数据保存在后台,同时增加用户登录的在线数量, 同时利用emit事件再向前台广播(发送事件),告诉前台当前登录的游湖有哪些,以及用户数量,同时将传递进来的当前登录用户也返回回去
再接着就是前台
监听后台发来的当前用户数据以及登录用户的总数据和总数量
// 接收到后台发来的在线用户,人数, 以及当前用户
this.Socket.on('login', res=>{
this.proccessPlatform('login', res)
});
proccessPlatform(state, res){
// 将传来的对象转换为数组
const arr = [];
for(let [k, v] of Object.entries(res.onlineUsers)){
arr.push({
uid:k,
username:v
})
}
this.platform.userList = arr;
this.platform.count = res.onlineCount;
this.logBol = false
this.message = `${res.user.userName}${state === 'login' ? '登录' : '离开了'}聊天室!`
},
接收到传来的值后,调用前台处理方法,用来存储传来的总用户数,以及数量。platform
为前台为了存储用户列表的对象userList
为用户数据列表count
:为总数量message
:为广播消息的值
将这些值都存储后,我们就可以将用户数据列表在HTML页面循环出来,同时还有数量总数。
到目前为止,我们的登录操作就已经完成了,接下来做的就是退出操作了,而退出操作是和登录几乎相同的,首先我们来看前台
退出的事件
前台关闭了socket后,后台index.js
可以监听到关闭的事件
注意这个事件是写在io.on()的方法中,和之前监听用户登录方法并列
首先要组成一个新的用户数据,用来告诉前端当前还有哪些用户在线已经总的数量
同时向前台发送logout事件,用来广播最新的用户数据列表、用户总量、哪位用户退出了
前台
监听后台发送来的logout
事件,监听到后,调用之前写好的proccessPlatform
方法
// 退出事件发送过来后,当前用户是接收不到这个事件中的数据的
this.Socket.on('logout', res=>{
this.proccessPlatform('logout', res)
})
目前为止,已经完成了用户登录以及用户退出的的方法,前台也可以接收到后台发送来的事件进行广播。
- 最后就是要做的用户聊天发送消息的处理
首先是前台点击发送后,触发的发送事件
// 给后台发送用户输入消息
send(){
const req = {
...this.user, //当前用户发送
content:this.content, // 输入框中的值
}
this.Socket.emit('message', req) // 告诉后台用户发送了消息
// 我自己发的消息先行存在本地
this.msgList.push({
...req,
isMe:true // 判断是不是我发送的消息
})
// console.log(this.msgList)
this.content = '' // 发送成功后清空输入框中的值
},
后台对前台发送的消息事件做处理,在这里我们使用的和之前处理方法不一样,因为是发送消息,所以肯定会有是不是我发送的消息之分,所以使用的另外一个发送API,这样当前用户发送消息后,就不会向前台广播,而我们只需要在前台先行将我们发送的消息存储到本地列表中,这也就是我们上面缩写的前台处理事件中的push方法
注意这个事件是写在io.on()的方法中,和之前监听用户登录方法并列
// 监听客户端发送过来的数据
socket.on('message', res=> {
// 发送过来消息,进行广播
// console.log(res);
// io.emit('message', res) // 废弃(能够向所有用户发送消息)
socket.broadcast.emit('message', res); // 只会向除了自己的其他用户发送消息
})
接下来就是前台监听后台发来的message
事件,在处理完后,将数据存储到前台消息列表中
// 后台广播数据
this.Socket.on('message', res=>{
// 接收到的都是用户发来的消息,肯定不是自己的,所以每一个都要设置isMe为false
res.isMe = false;
this.msgList.push(res)
})
msgList
:前台的消息列表
将拿到的消息列表循环显示到页面中就可以了
目前为止,整个聊天室算是基本完成了。
项目源码地址:https://github.com/BedRockGx/Socket