前几天在网上看到了关于websocket的一些视频教程,所以就在学习了以后做了这个项目,总结一下在做这个项目过程中遇到的一些问题
效果图
图片经过压缩,展示效果不是很好
关于socket通信的简单说明
Socket是在应用层和传输层之间的一个抽象层,它把TCP/IP层复杂的操作抽象为几个简单的接口,供应用层调用实现进程在网络中的通信(来源百科)。它是一种全双工(服务端与客户端可同时收发消息)通信,当有数据更新时服务端可以主动的将消息推送到客户端。
Socket通信的运行流程如下
1、服务端启动Socket监听端口,监听是否有客户端连接进来,即Watch Socket;
2、客户端通过http协议发送请求报文,服务端响应请求后会将协议升级为WebSocket,并创建一个新>的Socket对象,客户端Socket随即与服务端Socket进行连接和通信,且客户端不再与Watch Socket通信;
3、Watch Socket继续监听是否有其它客户端连接。
项目地址
基于vue+koa2+socket.io实现多人在线实时聊天(客户端)
后端
技术栈
- node
- koa2
- socket.io
socket.io的使用
socket.io提供了基于事件的实时双向通讯,它同时提供了服务端和客户端的API。
服务端
服务端socket.io必须绑定一个http.Server实例,因为WebSocket协议是构建在HTTP协议之上的,所以在创建WebSocket服务时需调用HTTP模块并调用其下createServer()方法,将生成的server作为参数传入socket.io。
var httpServer = require('http').createServer();
var io = require('socket.io')(httpServer);
httpServer.listen(3000);
项目代码
socket.on( ) :订阅一个事件
socket.emit( ) : 告诉当前用户
io.emit( ) : 广播事件
const Koa = require("koa")
const app = new Koa()
const cors = require("koa2-cors")
// 解决跨域
app.use(cors())
//核心,初始化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); //核心,实现客户端之间交互通信
let users = [] //存储所有用户的数组
io.on("connection", socket => {
socket.on("submit", (data) => {
let result = users.find(item => {
return item.userName == data.userName
})
socket.emit("login", result)
if (!result) {
// 存储当前登陆用户的信息
socket.userName = data.userName
socket.avatar = data.avatar
// 加入到用户数组
users.push(data)
socket.emit("loginSuccess", data)
io.emit("addUser", data)
io.emit("userList", users)
}
})
//发送信息
socket.on("sendMsg", data => {
io.emit("sendAll", data)
})
//发送图片
socket.on("sendFile", data => {
io.emit("sendFileAll", data)
})
// 用户断开连接的时候
socket.on('disconnect', () => {
// 把当前用户的信息从users中删除掉
let idx = users.findIndex(item => item.userName === socket.userName)
// 删除掉断开连接的这个人
users.splice(idx, 1)
// 1. 告诉所有人,有人离开了聊天室
io.emit('delUser', {
userName: socket.userName,
avatar: socket.avatar
})
// 2. 告诉所有人,userList发生更新
io.emit('userList', users)
})
})
server.listen(3000, () => {
console.log(`监听地址: http://localhost:3000`);
})
前端
技术栈
- vue
- vue-socket.io
- scss
vue-socket.io
安装
npm install vue-socket.io --save
引入
//main.js
import VueSocketIO from 'vue-socket.io'
Vue.use(new VueSocketIO({
debug: true, //设置true可以让你的控制台文字变颜色,更好的调试阅读
connection: 'http://localhost:3000',
}))
vue-socket.io订阅事件
注意:这段代码是和你的methods、mounted等生命周期同级的
(vue-socket.io 3.0.9版本因为出现了无法触发sockets里订阅的事件的bug,所以尽量不要使用3.0.8,和3.0.9版本的,也有解决办法,后面会讲)
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")
},
getMsg(data){
console.log("后端传过来的消息",data)
this.speak = data
}
}
关于 vue-socket.io 3.0.8版本和3.0.9版本存在的bug
在 vue-socket.io 3.0.9 版本中会出现无法接收到信息的 bug (也就是你在 sockets中定义的方法是没有办法触发的) ,关于这个问题我们可以通过以下方法解决
方法一: this.sockets.listener.subscribe
this.sockets.listener.subscribe("事件名", (参数) => {
//逻辑
})
方法二 :使用 socket.io-client
import io from 'socket.io-client'
export default {
mounted() {
io('http://127.0.0.1:8080').on('hi', (res) => {
console.log('socket.io-client', res)
})
},
}
以上两种解决办法可以文章 :vue-socket.io3.08,3.09有bug接收不到数据
这个版本是不存在该bug的
vue 渲染页面后div的滚动条保持在最底部的方法
因为在用户发送信息时,我们需要实时查看到最新的休息,所以需要让滚动条保持到最底部,在网上查看了好几种方法,但是在vue中还是有些不太适用,但是还是记录下来
关于$nextTick
Vue 实现响应式并不是数据发生变化之后 DOM 立即变化,而是按一定的策略进行 DOM 的更新。
$nextTick 是在下次 DOM 更新循环结束之后执行延迟回调,在修改数据之后使用 $nextTick,则可以在回调中获取更新后的 DOM
方式一:
//每次页面渲染完之后滚动条在最底部
updated:function(){
this.$nextTick(function(){
var p = document.getElementById('dialogue_box');
p.scrollTop = p.scrollHeight;
})
}
方式二:
亲测该方法在发送图片时会有bug
//processData 是双向绑定的数据
watch: {
'processData': 'scrollToBottom'
}
methods:{
scrollToBottom: function () {
this.$nextTick(() => {
var div = document.getElementById('data-list-content')
div.scrollTop = div.scrollHeight
})
}
}
转自http://www.yemengs.cn/article?id=5ecb913c401f514d37d6e0d4&distance=0&page=2