实现简易的群聊天室
进入对应的文件夹
npm init -y (将会生一个package.json描述当前项目的基本信息)
# 安装socket.io
npm install --save socket.io
整理业务场景与实现思路:
-
实现群聊。
-
当打开群聊页面时,建立
websocket
连接,每当有客户端连接成功,即当做进入该群聊天室。 -
点击发送按钮,可将自己写的消息,发送给服务端,由服务端转发给聊天室的所有人。
-
客户端接收服务端返回的消息,显示在聊天记录列表中。
-
-
统计并更新在线人数。
-
在服务端维护一个全局变量:count=0;用于表示当前在线人数。
-
服务端一旦监听到客户端连接成功,count++
-
服务端一旦监听到客户端连接断开,count--
-
只要count一有变化,就需要向所有客户端发消息(
countmsg
),更新在线人数。 -
客户端接收
countmsg
消息,更新人数即可。
-
服务器端 node.js
// 引入相关模块 监听客户端的连接
const http = require('http').createServer()
const socketio = require('socket.io')(http, {
cors: { origin:'*' } // 允许所有域名访问
})
let count = 0
// 监听连接的建立
socketio.on('connection', function(socket){
console.log('有客户端进来了:' + socket.id)
// 更新在线人数
count++
socketio.emit('countmsg', count)
// 监听socket的断开,一旦连接断开,则count--
socket.on('disconnect', function(){
count--
socketio.emit('countmsg', count)
})
// 监听客户端发过来的消息
socket.on('textmsg', function(data){
socketio.emit('textmsg', data) // 收到什么就给所有客户端都发一遍
})
})
http.listen(5050, ()=>{
console.log('服务器已启动...')
})
服务器端完成以后接下来就是我们的客户端,我们可以先准备一个登录页面,让用户注册自己的昵称,代码如下
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>微信聊天室</title>
<link rel="stylesheet" href="styles/normalize.css">
<link rel="stylesheet" href="styles/reset.css">
<link rel="stylesheet" href="styles/chart.css">
</head>
<body>
<div id="login-container">
<div class="login-title">微信聊天室</div>
<div class="login-user-icon">
<img src="images/login.png" alt="">
</div>
<div>
<input type="text" id="username" class="login-item login-username" placeholder="请输入聊天昵称">
</div>
<div>
<input type="button" id="login" class="login-item login-button" value="登录">
</div>
</div>
<script>
login.onclick = function(){
// 准备name与avatar名
let name = username.value
let avatar = Math.floor(Math.random()*100)+".jpg"
window.location = `chart.html?name=${name}&avatar=${avatar}`
}
</script>
</body>
</html>
运行结果如下
用户登录以后就可以来到聊天界面进行聊天
如果用户没有注册昵就直接打开聊天界面就会跳转到登录页面
打开两个聊天室,进行检测
聊天页面的代码如下
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>微信聊天室</title>
<link rel="stylesheet" href="styles/normalize.css" />
<link rel="stylesheet" href="styles/reset.css" />
<link rel="stylesheet" href="styles/chart.css" />
</head>
<body>
<div id="chart-container">
<div class="chart-user-list" id="chart-user-list">
<div class="user-item">
<img src="images/avatar/15.jpg" alt="" />
未知名
</div>
</div>
<div class="chart-main-area">
<div class="chart-main-title">
<h1>
微信聊天室(<span id="userNumber"></span>人)-<span
id="currentUser"
></span>
</h1>
</div>
<div class="chart-list" id="chart-list">
<!-- <div class="user-logined" id="user-logined"><span id="logined-user"></span>上线了</div> -->
<!-- <div class="chart-item">
<div class="user-face"><img src="images/avatar/11.jpg" alt=""></div>
<div class="user-message">111</div>
</div> -->
</div>
<div class="chart-form">
<div>
<textarea class="chart-form-message" id="message"></textarea>
</div>
<div>
<input
type="button"
id="send"
class="chart-form-send"
value="发表"
/>
</div>
</div>
</div>
</div>
<script src="scripts/socket.io.js"></script>
<script>
// 判断,如果不是登录过来的,则跳转回登录页面
let search = decodeURI(window.location.search) // 拿到浏览器地址栏的查询字符串
if (!search) {
window.location = 'index.html'
}
let name = search.split('&')[0].split('=')[1]
let avatar = search.split('&')[1].split('=')[1]
console.log(`name:${name} avatar:${avatar}`)
// 更新页面中的头像与昵称
let userInfoDiv = document.getElementById('chart-user-list')
userInfoDiv.innerHTML = `<div class="user-item">
<img src="images/avatar/${avatar}" alt="">
${name}
</div>`
// 建立websocket连接
let socket = io('http://127.0.0.1:8081')
console.log('连接成功', socket)
// 监听服务端返回的更新人数的消息
socket.on('countmsg', function (data) {
userNumber.innerHTML = data //更新span,显示最新的人数
})
// 监听服务端返回的消息
socket.on('textmsg', function (data) {
console.log('服务端发回:', data)
// 追加到聊天记录列表中
let list = document.getElementById('chart-list')
let html = list.innerHTML
html += `<div class="chart-item">
<div class="user-face"><img src="images/avatar/${data.avatar}" alt=""></div>
<div style="font-size:0.9em;">${data.name}</div>
<div class="user-message">${data.content}</div>
</div>`
list.innerHTML = html
// dom操作,使list的滚动条持续在底部
list.scrollTop = list.scrollHeight
})
// 点击发表按钮,发送消息
send.onclick = function () {
if (message.value && message.value.length < 30)
//发送消息 {content:xx, name:xx, avatar:xx}
socket.emit('textmsg', {
content: message.value,
name,
avatar,
})
message.value = ''
}
</script>
</body>
</html>