websocket和原生js实现实时聊天系统
因为把websocket学了点,就想自己写一个实时聊天系统,主要效果如下:
用到的东西也不多。代码粘贴在这里:
//index.js
const ws = require('nodejs-websocket')
const PORT = 3000
let names = {}
let server = ws.createServer(connect => {
let name = ''
// 监听用户传递过来的数据,text事件会被触发
connect.on('text', data => {
data = JSON.parse(data)
if (data.isLogin) {
// 对用户首次登录进行验证
name = data.nickName
if (names[name]) {
broadcast({
msg: '该用户名已经登录',
Login: false
})
} else {
names[name] = name
// 通知所有人新用户进入聊天室
broadcast({
msg: `用户${names[name]}进入聊天室`,
Login: true,
names
})
}
} else {
broadcast({
msg: data.msg,
nickName: names[name]
})
}
})
//监听客户端关闭,close事件会被触发
connect.on('close', () => {
broadcast({
msg: `用户${names[name]}离开聊天室`,
Level: true,
name: names[name]
})
names[name] = ''
})
//发生错误时,error会被触发
connect.on('error', () => {
})
})
server.listen(PORT, () => {
console.log(`正在监听${PORT}`);
})
// 定义广播函数,给所有用户发送信息
function broadcast(msg) {
//server.connections: 表示所有的用户
server.connections.forEach(item => {
item.send(JSON.stringify(msg))
})
}
//index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>websocket基本使用</title>
</head>
<style>
* {
margin: 0;
padding: 0;
list-style: none;
}
html, body {
width: 100%;
height: 100%;
}
body {
background: url(https://z3.ax1x.com/2021/10/11/5ZqMD0.jpg) no-repeat;
background-size: 100% 100%;
background-position: center center;
backdrop-filter: blur(20px);
overflow: auto;
}
.login {
width: 300px;
height: 300px;
border: 1px solid pink;
position: fixed;
left: 0;
right: 0;
top: 0;
bottom: 0;
margin: auto;
text-align: center;
}
.login span {
font-size: 28px;
color: snow;
position: relative;
top: 20px;
}
.bBox {
position: relative;
top: 40px;
}
.loginInput {
width: 80%;
height: 24px;
border: 1px solid pink;
border-radius: 2px;
padding-left: 3px;
outline: none;
}
.box {
position: relative;
top: 60px;
left: 5px;
}
ul {
display: flex;
flex-wrap: wrap;
}
ul>li {
width: 50px;
height: 50px;
margin: 2px;
}
li>img {
width: 50px;
height: 50px;
}
.now {
border: 1px solid skyblue;
}
.consumer {
width: 600px;
height: 400px;
border: 1px solid black;
position: fixed;
top: 0;
left: 0;
right: 0;
bottom: 0;
margin: auto;
background-color: #fff;
}
.showBox {
width: 100%;
height: 80%;
display: flex;
border-bottom: 1px solid black;
}
.content {
flex: 1;
}
.userInfo {
width: 20%;
height: 100%;
border-left: 1px solid black;
}
.userIn {
display: flex;
height: 20%;
}
.userInput {
flex: 1;
outline: none;
border: none;
}
.userBtn {
width: 20%;
border: none;
}
.userBtn:hover {
background-color: #ccc;
}
</style>
<body>
<!-- 登录 -->
<div class="login">
<span class="loginSpan">登录</span>
<div class="bBox">
<input type="text" class="loginInput" placeholder="请输入昵称">
<button class="loginBtn">登录</button>
</div>
<div class="box">
<ul>
<li><img src="https://z3.ax1x.com/2021/10/11/5ZX7GD.png" alt=""></li>
<li><img src="https://z3.ax1x.com/2021/10/11/5ZXbxH.png" alt=""></li>
<li><img src="https://z3.ax1x.com/2021/10/11/5ZXTPO.png" alt=""></li>
<li><img src="https://z3.ax1x.com/2021/10/11/5ZXIIK.png" alt=""></li>
<li><img src="https://z3.ax1x.com/2021/10/11/5ZXLMd.png" alt=""></li>
<li><img src="https://z3.ax1x.com/2021/10/11/5ZXOsA.png" alt=""></li>
<li><img src="https://z3.ax1x.com/2021/10/11/5ZXXqI.png" alt=""></li>
<li><img src="https://z3.ax1x.com/2021/10/11/5ZXvZt.png" alt=""></li>
<li><img src="https://z3.ax1x.com/2021/10/11/5ZXxdP.png" alt=""></li>
<li><img src="https://z3.ax1x.com/2021/10/11/5ZXzIf.png" alt=""></li>
</ul>
</div>
</div>
<!-- 聊天室 -->
<div class="consumer" style="display: none;">
<div class="showBox">
<div class="content"></div>
<div class="userInfo"></div>
</div>
<div class="userIn">
<input type="text" class="userInput">
<button class="userBtn">发送</button>
</div>
</div>
<script>
//登录界面处理功能
let login = document.querySelector('.login')
let loginSpan = document.querySelector('.loginSpan')
let loginInput = document.querySelector('.loginInput')
let lis = document.querySelectorAll('li')
let loginBtn = document.querySelector('.loginBtn')
//聊天界面处理功能
let consumer = document.querySelector('.consumer')
let content = document.querySelector('.content')
let userInfo = document.querySelector('.userInfo')
let userInput = document.querySelector('.userInput')
let userBtn = document.querySelector('.userBtn')
let userImg = ''
let nickName = ''
lis.forEach(item => {
item.addEventListener('click', event => {
clearBoth(lis)
event.srcElement.className = 'now'
userImg = event.srcElement.currentSrc
})
})
function clearBoth(arr) {
arr.forEach(item => {
item.firstChild.className = ''
})
}
//创建连接
let socket = new WebSocket('ws://localhost:3000')
//登录按钮点击,并发送请求进行验证
loginBtn.addEventListener('click', () => {
nickName = loginInput.value
socket.send(JSON.stringify({
userImg,
nickName,
isLogin: true
}))
})
//发送信息按钮点击,发送到所有人都能看到
userBtn.addEventListener('click', () => {
socket.send(JSON.stringify({
msg: userInput.value,
nickName
}))
userInput.value = ''
})
//监听从服务端发送过来的数据
socket.onmessage = function(msg) {
let data = JSON.parse(msg.data)
//处理第一次登录
if(data.Login) {
login.style.display = 'none'
consumer.style.display = 'block'
// 给所有人显示新用户上线
let dv = document.createElement('div')
dv.innerHTML = data.msg
dv.style.color = 'aqua'
content.appendChild(dv)
//在用户列表显示新用户
//笨方法,首先将里面所有的都删了
userInfo.innerHTML = ''
for(let item in data.names) {
let dvIn = document.createElement('div')
dvIn.innerHTML = item
dvIn.className = item
userInfo.appendChild(dvIn)
}
} else if(typeof data.login === 'Boolean') {
//处理已经登录过的用户
alert('该用户已经登录')
} else if(data.Level) {
console.log(data);
//处理有用户离开的时候
let dv = document.createElement('div')
dv.innerHTML = data.msg
dv.style.color = 'red'
content.appendChild(dv)
//用户表删除一个用户
//获取要被删除的用户
let deUser = document.getElementsByClassName(data.name)[0]
userInfo.removeChild(deUser)
} else {
//处理普通聊天信息的
let dv = document.createElement('div')
dv.innerHTML = data.nickName + ':' + data.msg
dv.style.color = 'pink'
content.appendChild(dv)
}
}
</script>
</body>
</html>
行百里者半九十