共 4 条评论关于"基于vue+koa2+socket.io实现多人在线实时聊天"
最新评论
在群里看到好几次有关于websocket通信问题,作为一个前端,为嘛要懂的那么多,说好的一起做好切图仔呢,还能不能愉快地玩耍,哎!真叫人捉急。于是乎也去研究一番多人群组聊天室,发现还是有点意思,有那么点成就感的。
实现多人在线实时聊天,即,类似于QQ群聊聊天室功能,支持用户上线下线通知(demo暂未实现,觉得没意思了,通信已经完全打通,剩下的都是业务层问题)、当前在线实时人数等。技术站:前端vue.js+vue-socket.io,服务端:node.js+koa2+mongodb+socket.io
是对websocket的封装。并不是所有的客户端都可以支持websocket。如果支持websocket,那么socket.io就等同于websocket。socket.io还用到了其它的技术来模拟websocket,所以当你是用socket.io的时候,不管浏览器是否支持websocket,你都可以实现异步操作。当然如果你的客户端是用了socket.io,server端也必须对应使用。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 | const Koa = require('koa'); const app = new Koa();//实例化 const Router = require('koa-router'); //注意:引入的方式 const bodyParser = require('koa-bodyparser');//处理post请求 const cors = require('koa2-cors');// CORS是一个W3C标准,全称是"跨域资源共享" const { connect, initSchemas } = require("./mongodb"); const mongoose = require('mongoose'); //核心,初始化app作为HTTP 服务器的回调函数像express这么写mac电脑会有问题,无法访问 // const server = require('http').Server(app); //express写法 const server = require('http').Server(app.callback()); //koa正确姿势 const io = require('socket.io')(server); //核心,实现客户端之间交互通信 <!-----------------------省略一小坨代码,这不是本次demo重点-------------------------> let sum = 0; io.on('connection', socket => { console.log('初始化成功!'); const Message = mongoose.model('Message') Message.find({}, function (err, res) { io.emit('getMsg', res); }) //新人进来在线人数+1 socket.on('users',data=>{ sum = sum + 1; io.emit('users',sum); //将消息发送给所有人。 }) //disconnnect断开,自带函数方法 socket.on('disconnect',data=>{ console.log('用户断开了'); sum = sum - 1; io.emit('users',sum); //将消息发送给所有人。 }) socket.on('send', data => { // console.log('客户端发送的内容:',data, data['name'], data['getMsg']); try { const Message = mongoose.model('Message') let oneUser = new Message({ name: data['name'], msg: data['getMsg'] }) oneUser.save().then(() => { const Message = mongoose.model('Message') let dataArry = Message.find({}, function (err, res) { console.log('获取到数据', res) socket.emit('getMsg', res); //通知触发该方法的客户端 io.emit('getMsg', res); //通知所有客户端 }) }) } catch (error) { console.log("失败",error) } }) }) server.listen(process.env.PORT || port, () => { console.log(`监听地址: http://127.0.0.1:${port}`); }) |
1 2 3 4 5 6 | import VueSocketIO from 'vue-socket.io' //核心 Vue.use(new VueSocketIO({ debug: true, //设置true可以让你的控制台文字变颜色,更好的调试阅读 connection: 'http://172.18.30.90:3000', })) |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 | <template> <div class="content"> <!-- <h1>{{ msg }}</h1> --> <h1>多人实时在线聊天</h1> <p>当前在线人数:{{userNmber}}</p> <input type="请输入内容" v-model="inValue" @keyup.enter="btn_sbmit"> <input type="button" value="发送" @click="btn_sbmit"> <ul> <!-- 最新加入 --> <li v-if="newUser">有新人加入</li> <li v-for="(item,index) in speak" :key="index" :class="{active:item.name == userStorage}"> <span> <font v-if="item.name == userStorage">:</font> {{item.name}} <font v-if="item.name != userStorage">:</font> </span> {{item.msg}} </li> </ul> </div> </template> <script> export default { name: 'HelloWorld', props: { msg: String }, data() { return { speak:[], //聊天记录 inValue:'', //当前输入信息 userIp:'未知用户', userStorage: localStorage.getItem("userId"), newUser:false, //是否有新人加入 userNmber: 0 //在线人数 } }, created () { fetch('http://172.18.30.90:3000/home/b') .then(function(response) { return response.json(); }) .then(function(myJson) { //console.log(myJson); }); }, mounted () { this.$socket.emit('connect', 1); console.log(this.userStorage) }, methods: { //提交向后端发送数据 btn_sbmit() { if(!localStorage.getItem("userId")){ this.userIp = this.formatDateTime() + Math.random().toString(36).substr(2); this.speak.push({'name':this.userIp.substr(-5, 5),msg:this.inValue}) this.$socket.emit("send",{name:'用户'+this.userIp.substr(-5, 5), getMsg:this.inValue}) localStorage.setItem("userId",'用户'+this.userIp.substr(-5, 5)); this.userStorage = localStorage.getItem("userId"); }else{ this.speak.push({'name':localStorage.getItem("userId"),msg:this.inValue}) this.$socket.emit("send",{name:localStorage.getItem("userId"), getMsg:this.inValue}) } this.inValue = '' }, //生成id formatDateTime(){ var date = new Date(); var y = date.getFullYear(); var m = date.getMonth() + 1; m = m < 10 ? ('0' + m) : m; var d = date.getDate(); d = d < 10 ? ('0' + d) : d; var h = date.getHours(); var minute = date.getMinutes(); var second = date.getSeconds(); return y + m + d + h + minute + second; } }, sockets:{ connect(data){ if(data){ console.log('连接成功',data) this.$socket.emit("users") } }, users(data){ console.log("在线人数",data) this.userNmber = data; }, reconnect(data){ console.log('重新连接',data) }, disconnecting(data){ console.log('socket已断开连接'); this.$socket.emit("users") }, //有新人加入 // userinfoNumber(data){ // this.userNmber = true; // }, getMsg(data){ console.log("后端传过来的消息",data) this.speak = data } } } </script> |
注意:这段代码是和你的methods、mounted等生命周期同级的
Socket.IO内置了一些默认事件,我们在设计事件的时候应该避开默认的事件名称,并灵活运用这些默认事件钩子是很有必要的。
1 2 3 4 | io.sockets.on(‘connection’, function(socket) {}):socket连接成功之后触发,用于初始化 socket.on(‘message’, function(message, callback) {}):客户端通过socket.send来传送消息时触发此事件,message为传输的消息,callback是收到消息后要执行的回调 socket.on(‘anything’, function(data) {}):收到任何事件时触发 socket.on(‘disconnect’, function() {}):socket失去连接时触发(包括关闭浏览器,主动断开,掉线等任何断开连接的情况) |
1 2 3 4 5 6 7 8 9 10 | connect:连接成功 connecting:正在连接 disconnect:断开连接 connect_failed:连接失败 error:错误发生,并且无法被其他事件类型所处理 message:同服务器端message事件 anything:同服务器端anything事件 reconnect_failed:重连失败 reconnect:成功重连 reconnecting:正在重连 |
客户端socket发起连接时的顺序。当第一次连接时,事件触发顺序为:connecting->connect;当失去连接时,事件触发顺序为:disconnect->reconnecting(可能进行多次)->connecting->reconnect->connect。
上一篇:koa2-cors设置允许指定单个域名、多个域名、所有域名跨域
下一篇:利用node快速压缩图片、视频(突破某网站单次最多20张限制)
最新评论
支付宝扫一扫打赏
微信扫一扫打赏
你好大神,你这个demo有开放的github么?
@kong在github里koa中,不过没有单独剥离出来
@管理员还想着拿来学习学习的[捂脸]
@kong目前文章上面就是剥离的源码呀,只是你需要搭建环境和数据库才能跑起来