基于socket.io开发的聊天室demo
程序员文章站
2022-07-10 21:22:19
...
WebSocket比较不好的地方就是纯原生实现聊天室
// WebSocket的缺点,没有一个广播的事件或者说方法
// 需要我们自己去封装一个,封装一个广播事件的方法broadcast函数,并且broadcast函数内部职能发送字符串类型
// 如果你发送别的对象数组等等服务端就会报错,所以我们还需要用到JSON.stringify去转换一下发给前端,并且前端还需要哦转
// WebSocket的事件非常的少,用来用去就那几个事件方法
// 所以我们更多的是用一个框架去开发聊天室类的网站
// 我们使用socket.io这个框架去开发
// 我们基于socket.io开发一个完整的聊天室
我们基于socket.io做出来的demo聊天室
登录页面的demo样例图片
聊天的页面
为了更加的简单便捷的去开发一个websocket项目我们使用到了socket.io去开发
我们基于socket.io开发的demo文件夹层级关系
server.js
var express = require("express")
var app = express()
var server = require("http").Server(app)
var io = require("socket.io")(server)
// 记录已经登录过的用户
var users = []
app.use(express.static("./public"))
server.listen(8083, () => {
console.log("服务器8083开启成功~!")
})
app.get("/", function (req, res) {
res.redirect("/index.html")
})
io.on("connection", function (socket) {
// 用户连接的功能
socket.on("login", function (data) {
// 判断,如果data在user中存在,说明该用户已经登录了不允许登录
// 如果data在users中不存在,说明该用户没有登录,允许用户登录
var user = users.find(item => item.username === data.username)
if (user) {
// 表示用户存在,登录失败!服务器需要给当前用户响应,告诉登录失败
socket.emit("loginError", {
msg: "登陆失败"
})
console.log("登录失败!")
} else {
// 表示用户不存在,登录成功!
users.push(data)
socket.emit("loginSuccess", data)
console.log("登录成功!")
// socket.io广播消息如下
// socket.emit是告诉单个人的事件
// io.emit是广播给所有用户的事件
// 告诉所有的用户.目前聊天室谁进入聊天室
io.emit("addUser", data)
// 告诉所有的用户.目前聊天室中有多少人
io.emit("userList", users)
// 把登录成功的用户名和头像存储起来
socket.username = data.username
socket.avatar = data.avatar
}
})
// 用户断开连接的功能
// 监听用户断开连接
// 每个用户都有连接,如果浏览器断联就会自动触发disconnect事件
// 前端不需要写emit disconnect事件
socket.on("disconnect", function (data) {
// 把当前用户的信息从users中删除
var 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)
})
// 监听聊天的消息
socket.on("sendMessage",data=>{
console.log(data)
// 广播给所有的用户
io.emit("receiveMessage",data)
})
//接收图片信息
socket.on("sendImage",data=>{
console.log(data)
// 广播给所有的用户
io.emit("receiveImage",data)
})
})
index.js
/* global io */
/* global $ */
/* 聊天室的主要功能 */
// 1.连接socketio服务
var socket = io('http://localhost:8083')
var username, avatar
var toName = '群聊'
// 2.登录功能
$('#login_avatar li').on('click', function () {
$(this).addClass('now').siblings().removeClass('now')
})
// 点击按钮,登录
$('#loginBtn').on('click', function () {
// 获取用户名
var username = $('#username').val().trim()
if (!username) {
window.alert('请输入用户名')
return
}
if (username === '群聊') {
window.alert('用户名已存在')
return
}
// 获取选择的头像
var avatar = $('#login_avatar li.now img').attr('src')
console.log(username, avatar)
// 需要告诉socket io服务,登录
// 前端携带username和avatar去触发后端的login事件
socket.emit('login', {
username,
avatar
})
})
// 监听登录失败的请求
socket.on('loginError', data => {
window.alert('用户名已存在')
})
// 监听登录成功的请求
socket.on('loginSuccess', data => {
console.log('登录成功')
// 登录成功
// 隐藏登录窗口
// $('.login_box').fadeOut()
$('.login_box').hide()
// 显示聊天窗口
$('.container').fadeIn()
// 设置个人信息
$('.user-list .header img').attr('src', data.avatar)
$('.user-list .header .username').text(data.username)
username = data.username
avatar = data.avatar
})
// 监听添加用户的消息
socket.on('addUser', data => {
// 添加一条系统消息
$('.box-bd').append(`
<div class="system">
<p class="message_system">
<span class="content">${data.username} 加入群聊</span>
</p>
</div>
`)
scrollIntoView()
})
// 监听用户离开的消息
socket.on('delUser', data => {
// 添加一条系统消息
$('.box-bd').append(`
<div class="system leave">
<p class="message_system">
<span class="content">${data.username} 离开了群聊</span>
</p>
</div>
`)
scrollIntoView()
})
// 监听用户列表的消息
socket.on('userList', data => {
// 把userlist
$('.user-list ul').html('')
$('.user-list ul').append(`
<li class="user">
<div class="avatar"><img src="images/群聊.jpg" alt=""></div>
<div class="name">群聊</div>
</li>
`)
data.forEach(item => {
$('.user-list ul').append(`
<li class="user">
<div class="avatar"><img src="${item.avatar}" alt=""></div>
<div class="name">${item.username}</div>
</li>
`)
})
$('#userCount').text(data.length)
clickUser()
})
// 聊天功能
$('#btn-send').on('click', () => {
var content = $('#content').html().trim()
$('#content').html('')
if (!content) {
return window.alert('请输入内容')
}
// 发送消息给服务器
socket.emit('sendMessage', {
msg: content,
username,
avatar
})
})
// 监听接收聊天消息
socket.on('receiveMessage', data => {
console.log('收掉消息', data)
if (data.toName === '群聊') {
if (username === data.username) {
// 自己的消息
$('.box-bd').append(`
<div class="message-box">
<div class="my message">
<img src="${data.avatar}" alt="" class="avatar">
<div class="content">
<div class="bubble">
<div class="bubble_cont">${data.msg}</div>
</div>
</div>
</div>
</div>
`)
} else {
// 别人的消息
$('.box-bd').append(`
<div class="message-box">
<div class="other message">
<img src="${data.avatar}" alt="" class="avatar">
<div class="nickname">${data.username}</div>
<div class="content">
<div class="bubble">
<div class="bubble_cont">${data.msg}</div>
</div>
</div>
</div>
</div>
`)
}
} else {
if (username === data.username) {
// 自己的消息
$('.box-bd').append(`
<div class="message-box">
<div class="my message">
<img src="${data.avatar}" alt="" class="avatar">
<div class="content">
<div class="bubble">
<div class="bubble_cont">${data.msg}</div>
<div class="bubble_toName">私聊</div>
</div>
</div>
</div>
</div>
`)
} else {
// 别人的消息
$('.box-bd').append(`
<div class="message-box">
<div class="other message">
<img src="${data.avatar}" alt="" class="avatar">
<div class="nickname">${data.username}</div>
<div class="content">
<div class="bubble">
<div class="bubble_cont">${data.msg}</div>
<div class="bubble_toName">私聊</div>
</div>
</div>
</div>
</div>
`)
}
}
scrollIntoView()
})
// 当有消息时,将滑动到底部
function scrollIntoView () {
// 当前元素的底部滚动到可视区
$('.box-bd').children(':last').get(0).scrollIntoView(false)
}
// 发送图片功能
$('#file').on('change', function () {
var file = this.files[0]
// // 需要把这个图片发送到服务器,借助于H5新增的fileReader
var fr = new window.FileReader()
fr.readAsDataURL(file)
fr.onload = function () {
socket.emit('sendImage', {
username,
avatar,
img: fr.result,
toName
})
}
})
// 监听接收图片消息
socket.on('receiveImage', data => {
if (username === data.username) {
// 自己的消息
$('.box-bd').append(`
<div class="message-box">
<div class="my message">
<img src="${data.avatar}" alt="" class="avatar">
<div class="content">
<div class="bubble">
<div class="bubble_cont">
<img src="${data.img}">
</div>
</div>
</div>
</div>
</div>
`)
} else {
// 别人的消息
$('.box-bd').append(`
<div class="message-box">
<div class="other message">
<img src="${data.avatar}" alt="" class="avatar">
<div class="nickname">${data.username}</div>
<div class="content">
<div class="bubble">
<div class="bubble_cont">
<img src="${data.img}">
</div>
</div>
</div>
</div>
</div>
`)
}
// 等待图片加载完成
$('.box-bd img:last').on('load', function () {
scrollIntoView()
})
})
// 初始化jquery-emoji插件
$('.face').on('click', function () {
// 点击.face的时候再去初始化
$('#content').emoji({
// 设置触发表情包的表情按钮
button: '.face',
// 表示只有一组标签的时候显不显示tab
showTab: true,
animation: 'slide',
position: 'topRight',
icons: [{
name: 'QQ表情',
path: 'lib/jquery-emoji/img/qq/',
maxNum: 91,
excludeNums: [41, 45, 54],
file: '.gif'
}]
})
})
// // 扩展:私聊功能
// $('#btn-send').on('click', () => {
// var content = $('#content').html().trim()
// console.log(content)
// if (!content) {
// return window.alert('请输入内容')
// }
// if (toName === '群聊') {
// // 发送消息给服务器
// socket.emit('sendMessage', {
// msg: content,
// username,
// avatar,
// toName
// })
// } else {
// // 发送私聊消息给服务器
// socket.emit('sendMessageToOne', {
// msg: content,
// username,
// avatar,
// toName: toName
// })
// }
// $('#content').html('')
// })
// 点击用户事件绑定
function clickUser () {
$('.user').on('click', function () {
$(this).addClass('active').siblings().removeClass('active')
var to = $(this).children('.name').text()
$('#chatName').text(to)
toName = to
})
}
推荐阅读
-
微信门户开发框架-使用指导说明书(2)--基于框架的开发过程
-
详解基于node.js的脚手架工具开发经历
-
基于jQuery的弹出框插件开发教程
-
基于go语言结合微信小程序开发的微商城系统
-
基于NetCore+SqlSugar+Layui开发出来的开源框架项目FytSoaCms问题处理
-
【基于EF Core的Code First模式的DotNetCore快速开发框架】完成对DB First代码生成的支持
-
基于Maya API和PySide2的插件开发(用TextBrowser实现文件信息的显示)
-
基于wxpython开发的简单gui计算器实例
-
基于华为物联网IOT的应用开发 ---界面管理开发
-
基于JS开发微信网页录音功能的实例代码