上一篇文章介绍如何实现群聊和各种配置,这章是在上一篇的代码基础上介绍如何实现私聊功能,接下来我们先更新一下上篇文章的代码
服务端
① 在这里,我们添加一个监听登录的方法来获取客户端发送的 userId,以及获取对应的 socketId,并且push到数组中存储,用于我们后续查询;
注意:socketId 是不固定的,只是当前客户端在这个会话期间发送消息 socket.io 生成对应的 socketId,即某用户当前登录生产的 socketId 和下次登录生成的 socketId 是不一致的。
② 再添加一个 socket 实例对象监听的一个 disconnect 函数,旨在某个客户端断开连接时触发的事件,所以我们可以做类似退出登录的处理,将数组中对应的用户信息过滤。
io.on("connection", (socket) => {
// 自定义一个登录方法,用于获取用户的id和socketId,用户id用于后续查询socketId,而socketId就是实现私聊功能的核心
socket.on("login", ({ userId }) => {
// 此处我们接收一个对象,解构里面客户端传来的userId,并且将其push到用户信息列表中,用于我们在私聊方法中查询socketId
userList.push({
userId, // 用户id
socketId: socket.id, // 对应的socketId
});
console.log(userList);
});
// 自定义一个chat监听方法,当客户端发布到这个方法时,我们可以获取到发布的消息
socket.on("chat", (msg) => {
// 稍后将添加私聊的代码逻辑
});
// socket实例对象会监听一个特殊函数,关闭连接的函数disconnect,当用户断开链接,则将其信息于数组中删除
socket.on("disconnect", () => {
userList = userList.filter((i) => i.socketId != socket.id);
console.log(userList);
});
});
客户端
在客户端,我们要在登录页面,或者根据你实际的开发情况,在某个页面的调用服务端的登录方法,并且传 userId、time 等其他信息。
代码如下:
export default {
data() {
let msg = "";
return { msg };
},
methods: {
// 发布消息方法
send() {
// 发布到服务端,在服务端我们已经写好了对应的监听方法,只要有消息发布到服务端就会被接收到
this.$socket.emit("chat", {
userId: "",
msg: this.msg,
});
// 清空输入框
this.msg = "";
},
},
// socket内置的钩子,用来监听服务端发布的方法
sockets: {
// 在服务端自定义的发布方法
privateChatMessage(msg) {
console.log(msg);
},
},
mounted() {
// 服务端的登陆方法,你可以自己定义在哪个页面做这个登录逻辑:userId我则是用时间戳代替,在实际开发中当然还是用用户的userId
this.$socket.emit("login", { userId: new Date().getTime() });
},
};
私聊功能逻辑
在服务端,我们定义一个私聊事件,获取客户端发来的userId,查询对应的socketId,具体代码逻辑和注释如下:
// 自定义一个chat监听方法,当客户端发布到这个方法时,我们可以获取到发布的消息
socket.on("chat", ({ userId, msg }) => {
// broadcast: 是指发布到全部客户端但不发布到发消息的那个客户端,即你发送了消息,但是服务端不会返回给你
// socket.broadcast.emit("advertise", msg);
// 获取客户端发来的userId,查询对应的socketId
let index = userList.findIndex((i) => i.userId == userId);
// 定义私聊事件,核心是使用 socket 实例内置的to()方法,来指定一个socketId,并且发送到对应的客户端
socket.to(userList[index].socketId).emit("privateChat", msg);
});
methods: {
// 发布消息方法
send() {
// 发布到服务端,在服务端我们已经写好了对应的监听方法,只要有消息发布到服务端就会被接收到
this.$socket.emit("chat", {
userId: "",
msg: this.msg,
});
// 清空输入框
this.msg = "";
},
},
// socket内置的钩子,用来监听服务端发布的方法
sockets: {
// 在服务端自定义的群聊方法
advertise(msg) {
console.log(msg);
},
// 在服务端自定义的私聊方法
privateChat(msg) {
console.log(msg);
},
},
实践一下
先打开三个页面,然后指定一个页面的socketId进行私聊,注意服务端修改了代码需要重启一下
控制台打印三个用户的信息
这里我们取第二个页面的 userId 作为接收方,这里只是写死做测试,实际开发中的代码逻辑由你定义
接下来我们在第一个页面发送消息
结果如下,在第二个页面打印出了消息,而第三个页面则没有打印即没接收到消息
至此,我们的私聊功能已经基本完成,当然,在实际的开发环境中,还需要添加各种模块和功能以及对接后端的聊天数据存储,才是比较完善的聊天系统。
下篇文章会讲到如何在宝塔中部署node项目并让你的代码在生产环境中正常运行,最后会在发布一篇有关群聊的文章,如果有疑惑可以在评论区留言,我每天都会追踪最新动态,如果有帮助就留下你的赞或关注吧