1、 后端环境搭建
# npm init # npm install -s express # npm install -s socket.io
npm init 会生成json文件作为依赖包,express和socket.io插件安装完成后会生成node_modules文件夹和package-lock.json锁依赖文件,该文件记录插件的版本。
完成以上步骤并创建index.js文件作为后端的入口文件。
2、 后端入口文件
1)在index,js内首先需要引入已经安装的插件
/* 引入插件 */ const express = require('express') const socket = require('socket.io') const app = express()
2)需要设置跨域访问
/* 设置跨域访问 */ app.all('*', function (req, res, next) { res.header("Access-Control-Allow-Origin", "*"); res.header('Access-Control-Allow-Headers', 'Content-Type, Content-Length, Authorization, Accept, X-Requested-With , yourHeaderFeild'); res.header("Access-Control-Allow-Methods", "PUT,POST,GET,DELETE,OPTIONS"); res.header("X-Powered-By", ' 3.2.1') res.header("Content-Type", "application/json;charset=utf-8"); next(); });
3)监听端口号并响应前台请求
/* 监听端口号 */ const server = app.listen(4000,()=>{ console.log('正在监听4000端口...') }) /* 监听前端请求事件 */ const io = socket(server) let num = 0 //在线总人数 io.on('connection',(socket) => { // 响应连接(响应体) }
当前台使用io.connect()连接端口号的时候,后端就会监听到并响应。以下代码都在响应体内
4)响应体 -- 监听某某上线
let auther = null //上线人名称 num++ // 上线 socket.on('online',(name)=>{ console.log(name+'上线 ') auther = name const obj = { num: num, name: name } io.sockets.emit('online',obj) })
某某上线时,需要先将上线总人数加一,前台连接完成后马上就会向后台传递名称name给online事件,后台监听到online事件,记录上线人的名称,这里主要用于后面的离线。然后将某某上线的信息通过io.sockets广播给所有(包括自己)已经连接的页面。
5)响应体 -- 监听某某正在输入
// 监听正在输入... socket.on('typing',(name) => { socket.broadcast.emit('typing',name) });
当某某在input标签输入内容时,会将名称发给后台typing事件,后台监听typing并响应,通过socket.broadcast广播给所有页面(除了自己)
6)响应体 -- 监听发言
// 接收发言并返回 socket.on('chat',(data) => { io.sockets.emit('chat',data) console.log(data) });
某某在前台向后台chat事件发送信息(内容和名称),后台监听chat事件并响应,将信息广播给所有页面。
7)响应体 -- 监听离线
// 监听离线... socket.on('disconnect',()=>{ console.log(auther+'离线...') num-- const obj = { num: num, name: auther } io.sockets.emit('offline',obj) });
前台离开页面时会触发disconnect事件,后台监听到disconnect事件并作出响应,将之前保存的名称和减一的在线总人数广播给所有页面。到这里,后端的所有逻辑就已经准备就绪,可以启动后端了.......
3、 前台请求体
本次前台页面使用vue编写,
1) 引入socket.io(在vue项目的根页面index.html内引入),引入之后io就可以使用了
<script src="https://cdnjs.cloudflare.com/ajax/libs/socket.io/2.2.0/socket.io.dev.js"></script>
2) 在首页内需要先生成自己的名称(这里我随机生成名称 ),连接后台并把名称传给后台,告诉其他页面某某加入聊天了。这里我创建了一个类用于处理连接后台,该类一旦创建,constructor就会执行,因此就会连接后台并传递名称给后台,后台监听online并接受数据,然后广播给所有页面。
this.auther = '阿' + Math.floor(Math.random()*20) this.chat = new Chat(this.auther) //类chat内有connect方法 connect() { this.socket = io.connect('http://10.112.169.51:4000') this.socket.emit('online',this.name) }
3) 接收某某上线,已经向后台触发online事件,这时需要接收后台广播的上线人数和某某上线
this.chat.socket.on('online',(obj)=>{ this.title = `在线网友(${obj.num}人)` this.keypress = `${obj.name}加入聊天` })
4) 接收正在输入,当input有值的时候需要传名称给后台,后台也会广播给所有页面,同时需要接收广播的数据
watch: { value() { this.chat.socket.emit('typing', this.value.trim() ? this.auther : '') } },
this.chat.socket.on('typing',(data)=>{
this.keypress = data ? data+'正在输入...' : ''
})
5) 接收发言,前台通过发送按钮将发言信息和名称传给后台,后台广播给所有页面,所有需要接收广播信息
this.chat.socket.on('chat',(data)=>{ this.list.push({ imgUrl: require('@/assets/styles/images/asan.jpg'), auther: data.name, content: data.value, self: data.name === this.auther }) setTimeout(()=>{ if(this.scroll.maxScrollY) this.scroll.scrollTo(0,this.scroll.maxScrollY) },100)
})
6) 离线处理,前台在离开页面的时候会告诉后台断开连接。到此,前台的主要逻辑也已经完成(由于只附上主要逻辑,具体代码可看我的github前台,github后台),启动前台
disconnect() { this.socket.disconnect() }
4、流程图
5、效果图
6、参考文献
https://hackernoon.com/an-overview-of-frontend-and-backend-interaction-48l031ba