简约版聊天室
1.案例描述
本次项目利用express与socket.js
实现简约版聊天室,有用户登录及提示
用户退出及提示。聊天的显示
聊天室
2.静态页面
该页面主要有四大块区域
头部用户输入登录与退出功能
左侧用户聊天显示区域
右侧用户列表显示区域
底部用户输入聊天内容区域
2.1功能描述
当用户在头部的输入框输入内容
后,点击登录,右侧列表出现用户名字
左侧出现登录提示。点击底部输入聊天内容
点击发送左侧出现该用户的聊天内容。
点击头部退出按钮时用户列表该用户退出
左侧显示退出提示。
2.2静态页面代码
HTML:
javascript"><body onload="window_onload()" onunload="window_onunload()">
<h1>聊天室</h1>
<div id="divContainer1">
<table id="tbDlg" border="0" cellpadding="3" cellspacing="0" width="100%">
<tr id="trDlg">
<td id="tdDlg" width="5">
用户名:
<input type="text" value="游客" size="20" id="tbxUsername">
<input type="button" id="btnLogin" value="登录" onclick="btnLogin_onclick()">
<input type="button" id="btnLogout" onclick="btnLogout_onclick()" disabled value="退出">
</td>
</tr>
</table>
</div>
<div id="divLeft">
<div id="divchat"></div>
<div id="divContainer3">
<table id="tbDlg" border="0" cellpadding="3" cellspacing="0" width="0">
<tr id="trDlg">
<td valign="top" id="tdDlg" nowarp>对话</td>
<td valign="top" id="tdDlg" >
<textarea id="tbxMsg" cols="255" rows="5" style="width:100%"></textarea>
</td>
<td valign="top" id="tdDlg" nowarp>
<input type="button" id="btnSend" value="发送" disabled onclick="btnSend_onclick()">
</td>
</tr>
</table>
</div>
</div>
<div id="divRight">
用户列表:
</div>
</body>
<script src="/socket.io/socket.io.js"></script>
css:
h1{
font-size: 14pt;
color:#006bb5;
background-color: #f0f0f0;
border:1px solid #f0f0f0;
padding:5px;
margin-bottom: 18px;
border-radius: 5px;
color:purple
}
div[id^=divContainer]{
border:0;
margin:10px 0px 10px 0px;
padding:3px;
background-color: #f0f0f0;
border-radius: 5px;
}
div#divLeft{
width:85%;
background-color: #f0f0f0;
float: left;
}
div#divright{
width:15%;
background-color: white;
float: right;
font-size: 14px;
}
div#divchat{
border:0;
margin:10px 0 10px 0;
padding:3px;
background-color: #f0f0f0;
border-radius: 5px;
position: relative;
height:300px;
overflow: auto;
font-size: 14px;
font-size: 16px;
}
table#tbDlg{
background-color: #f0f0f0;
font-size: 14px;
}
tr#trDlg,td#tdDlg{
font-size: 14px;
}
textarea{
border:1px solid #444;
border-radius: 10px;
margin:5px;
color:black;
background-color: white;
width:100px;
font-size:16px;
}
input[type="button"]{
border:1px solid #808080;
border-radius: 20px;
width:80px;
background-color: #81a0b5;
}
input[type="button"]:hover{
background-color: #006bb5;
}
input[type="button"]:active{
margin:1px;
font-weight: bold;
background-color: #006bb5;
}
input[type="button"]:focus{
margin:0;
font-weight: bold;
background-color: #006bb5;
}
3.服务端代码
下载express npm i express
下载socket.io npm i socket.io
关于socket的使用,可参考官网
const express = require('express');
const app = express();
const http = require('http');
const server = http.createServer(app);
const { Server } = require("socket.io");
const io = new Server(server);
app.use(express.static(__dirname));
app.get('/',(req,res)=>{
res.sendFile(__dirname+'./index.html')
})
server.listen(8081,()=>{
console.log("it is ok")
})
var names=[]
io.sockets.on('connection',(socket)=>{
socket.on('login',name=>{
for(var i=0;i<names.length;i++){
if(names[i]==name){
socket.emit('duplicate')
return
}
}
names.push(name)
io.sockets.emit('login',name)
io.sockets.emit('sendClients',names)
})
socket.on('chat',data=>{
io.sockets.emit('chat',data)
console.log(data)
})
socket.on('logout',name=>{
for(var i=0;i<names.length;i++){
if(names[i]==name){
names.splice(i,1)
break
}
}
socket.broadcast.emit('logout',name)
io.sockets.emit('sendClients',names)
})
})
代码解析
该后端代码中,用names数组存放所有登录的用户名,用户登录时客户端与服务端建立连接,指定服务器接收到登录事件时(login)的处理逻辑。比如用户是否重复,发送duplicate事件。如果一切正常服务端发送sendClient事件
用来更新用户列表。当用户输入聊天内容后点击发送向服务器发送chat事件。服务端接收后向所有客户端发送chat事件。当用户点击退出
是向服务器发送logout事件,服务端接收,向所有客户端发送logout事件,以便处理用户退出后的逻辑。最后向所有客户端发送sendClients事件,实现界面更新。
4.js部分
启动只需在该文件所在目录终端
输入node server.js(你存放服务器代码文件的名字)
之后在游览器输入服务器监听的端口号
var userName,socket,tbxUsername,tbxMsg,divChat
function window_onload(){
divChat=document.getElementById('divchat')
tbxUsername=document.getElementById('tbxUsername')
tbxMsg=document.getElementById('tbxMsg')
tbxUsername.focus()
tbxUsername.select()
}
var color=['green','#006bb5','brown','crimson','purple']
function AddMsg(msg){
console.log(parseInt(Math.random(0,1)*color.length))
divChat.innerHTML+=msg+'<br/>'
divChat.style.color=color[parseInt(Math.random(0,1)*color.length)]
if(divChat.scrollHeight>divChat.clientHeight){
divChat.scrollTop=divChat.scrollHeight-divChat.clientHeight
}
}
function btnLogin_onclick(){
if(tbxUsername.value.trim()==''){
alert('请输入用户名')
return
}
socket =io()
userName=tbxUsername.value.trim()
socket.on('connect',function(){
AddMsg('连接聊天服务器')
socket.on('login',function(name){
AddMsg('欢迎'+name+'进入')
})
socket.on('sendClients',function(names){
var divRight=document.getElementById('divRight')
var str=''
names.forEach((name)=>{
str+=name+'<br/>'
})
divRight.innerHTML="用户列表:<br/>"
divRight.innerHTML+=str
})
socket.on("chat",data=>{
AddMsg(data.user+'说:'+data.msg)
})
socket.on("disconnect",()=>{
AddMsg("与服务器断开连接")
document.getElementById('btnSend').disabled=true
document.getElementById('btnLogout').disabled=true
document.getElementById('btnLogin').disabled=''
var divRight=document.getElementById('divRight')
divRight.innerHTML="用户列表"
})
socket.on("logout",name=>{
AddMsg("用户"+name+'已退出')
})
socket.on("duplicate",()=>{
AddMsg("改用户名已被使用")
document.getElementById('btnSend').disabled=true
document.getElementById('btnLogout').disabled=true
document.getElementById('btnLogin').disabled=''
divRight.innerHTML="用户列表"
})
})
socket.on("error",()=>{
AddMsg("与服务器连接失败")
socket.disconnect()
socket.removeAllListeners("connect")
io.sockets={}
})
socket.emit('login',userName)
document.getElementById('btnSend').disabled=''
document.getElementById('btnLogout').disabled=''
document.getElementById('btnLogin').disabled=true
}
function btnSend_onclick(){
var msg=tbxMsg.value
socket =io()
if(msg.length>0){
socket.emit('chat',{user:userName,msg:msg})
tbxMsg.value=''
}
}
function btnLogout_onclick(){
socket =io()
socket.emit('logout',userName)
socket.disconnect()
io.socket={}
AddMsg("用户"+userName+'已退出')
var divRight=document.getElementById('divRight')
divRight.innerHTML="用户列表"
document.getElementById('btnSend').disabled='disabled'
document.getElementById('btnLogout').disabled='disabled'
document.getElementById('btnLogin').disabled=''
}
function window_onunload (){
socket.emit('logout',userName)
socket.disconnect()
}
代码解析:
主要有六大函数,
window_onload | 用与文档一加载变后去对应的元素 |
AddMsg | 用于将用户输入的文字,服务器返回的信息进行显示 |
btnLogin_onclick | 用于与服务器建立连接,监听sendClients,login,chart等事件用于进行相应的js操作 |
btnSend_onclick | 向服务器发送输入框的文字 |
btnLogout_onclick | 断开与服务器的连接,进行html样式的改写 |
window_onunload |