一、前言

上一篇文章介绍了websocket的详细用法与工具类的封装,本篇就基于websocket搭建一个简易实时的聊天室。

在本篇开始之前也可以去回顾一下websocket详细用法:WebSocket详解与封装工具类

基于websocket与node搭建简易聊天室插图

二、基于node搭建后台websocket服务

首先确认本机电脑中是否安装node,可以通过cmd打开命令窗口运行node -v查看node版本;

  1. 建议创建一个空项目:
npm init
  1. 一路回车就行,然后就得到了一个package.json的配置文件;安装ws模块
npm i ws
  1. 新建app.js文件,源码如下:
const WebSocket = require('ws');
// 随机姓名
const names = ['赵', '钱', '孙', '李', '周', '吴', '郑', '王', '冯', '陈', '褚', '卫', '蒋', '沈', '韩', '杨', '朱', '秦', '尤', '许', '何',
'吕', '施', '张', '孔', '曹', '严', '华', '金', '魏', '陶', '姜', '戚', '谢', '邹', '喻', '柏', '水', '窦', '章', '云', '苏', '潘', '葛',
'奚', '范', '彭', '郎', '鲁', '韦', '昌', '马', '苗', '凤', '花', '方', '俞', '任', '袁', '柳', '酆', '鲍', '史', '唐', '费', '廉', '岑',
'薛', '雷', '贺', '倪', '汤', '滕', '殷', '罗', '毕', '郝', '邬', '安', '常', '乐', '于', '时', '傅', '皮', '卞', '齐', '康', '伍', '余',
'元', '卜', '顾', '孟', '平', '黄', '和', '穆', '萧', '尹'
];
// 获取随便昵称
const getRandom = (min, max) => {
return Math.floor(Math.random() * (min - max) + max)
};
// 创建 WebSocket 服务器实例
const wss = new WebSocket.Server({
port: 8080
});
// 监听连接事件
wss.on('connection', function(socket) {
console.log('新连接');
const randomIndex = getRandom(0, names.length - 1);
socket.nickname = names.splice(randomIndex, 1)[0];
sendMessageToClient( '连接成功!进入聊天室!');
// 监听接收消息事件
socket.on('message', function(message) {
sendMessageToClient(message);
});
// 监听接收消息事件
socket.on('close', function() {
// 广播消息给所有客户端
wss.clients.forEach(function each(client) {
if (client.readyState === WebSocket.OPEN) {
client.send(JSON.stringify({
nickname: socket.nickname,
msg: '退出聊天室!',
}));
}
});
});
// 监听接收消息事件
socket.on('error', function() {
// 广播消息给所有客户端
wss.clients.forEach(function each(client) {
if (client.readyState === WebSocket.OPEN) {
client.send(JSON.stringify({
nickname: socket.nickname,
msg: '网络不佳,连接失败 !',
}));
}
});
});
// 发送消息到客户端
function sendMessageToClient(message) {
let targetMsg = message instanceof Buffer ? message.toString() : message;
// 广播消息给所有客户端
wss.clients.forEach(function each(client) {
if (client.readyState === WebSocket.OPEN) {
client.send(JSON.stringify({
nickname: socket.nickname,
msg: targetMsg,
}));
}
});
}
});
  1. 最后启动node服务:node app.js;

三、前端构建聊天室

3.1 确定功能点

  1. 会话框中展示聊天内容;
  2. 输入框与发送按钮发送消息内容;
  3. 连接websocket,监听实时消息展示到界面中;

3.2 界面结构搭建

基于websocket与node搭建简易聊天室插图(1)

代码结构:

<div class="main_container">

<div id="msgList"></div>

<div class="controls">
<input type="text" class="pushMsg" />
<button id="btn">发送</button>
</div>
</div>

3.3 代码逻辑

  1. 引入之前封装的websocket工具类;

    <script src="./utils/websocket.js"></script>
    
  2. 实例化连接websocket;

    const newWebSocket = new WebSocketClient('ws:localhost:8080');
    newWebSocket.connect();
    
  3. 定义消息列表,监听返回消息信息,根据消息展示到界面中;

    // 消息列表
    const msgList = [];
    newWebSocket.addEventListener('message', handleMessage);
    // 处理返回数据
    function handleMessage(msg) {
    const msgData = JSON.parse(msg.data || '{}');
    console.log(msgData, "返回数据====");
    if (msgData && typeof msgData.msg === 'string' && !msgData.msg.includes('ping')) {
    msgList.push({
    name: msgData.nickname,
    msg: msgData.msg,
    });
    const str = msgList.reduce((cur, next) => {
    let curMsg = '';
    if (next.msg.includes('连接')) {
    curMsg = `玩家:${next.name}_${next.msg}`;
    } else {
    curMsg = `
    ${next.name}
    ${next.msg}
    `;
    }
    return cur += curMsg;
    }, '');
    $('#msgList').html(str);
    // 获取设置了滚动属性的div标签
    const div = document.getElementById('msgList');
    // 设置滚动的顶点坐标为滚动的总高度
    div.scrollTop = div.scrollHeight;
    }
    }newWebSocket.addEventListener('message', handleMessage);
    // 处理返回数据
    function handleMessage(msg) {
    const msgData = JSON.parse(msg.data || '{}');
    console.log(msgData, "返回数据====");
    if (msgData && typeof msgData.msg === 'string' && !msgData.msg.includes('ping')) {
    msgList.push({
    name: msgData.nickname,
    msg: msgData.msg,
    });
    const str = msgList.reduce((cur, next) => {
    let curMsg = '';
    if (next.msg.includes('连接')) {
    curMsg = `玩家:${next.name}_${next.msg}`;
    } else {
    curMsg = `
    ${next.name}
    ${next.msg}
    `;
    }
    return cur += curMsg;
    }, '');
    $('#msgList').html(str);
    // 获取设置了滚动属性的div标签
    const div = document.getElementById('msgList');
    // 设置滚动的顶点坐标为滚动的总高度
    div.scrollTop = div.scrollHeight;
    }
    }
    
  4. 监听输入框回车事件,与发送按钮点击事件,发送消息;

    // 监听发送按钮
    $('#btn').on('click', sendMessage);
    // 输入框回车事件
    $('.pushMsg').keydown(function(event) {
    if (event.key === 'Enter') {
    sendMessage();
    }
    });
    // 发送消息
    function sendMessage() {
    const msg = $('.pushMsg').val();
    if (msg) {
    newWebSocket.send(`${msg}`);
    $('.pushMsg').val('');
    }
    }
    

四、涉及小知识点

  1. 取消滚动条的展示,发送消息后默认展示最下方数据;

    #msgList::-webkit-scrollbar {
    width: 0;
    }
    
    // 获取设置了滚动属性的div标签
    const div = document.getElementById('msgList');
    // 设置滚动的顶点坐标为滚动的总高度
    div.scrollTop = div.scrollHeight;
    
  2. 输入框监听keydown事件,当key为Enter时发送消息(也可设置其他按键)

    // 输入框回车事件
    $('.pushMsg').keydown(function(event) {
    if (event.key === 'Enter') {
    sendMessage();
    }
    });
    
  3. 取消input的光标进入的表框效果

    outline: none;
    
  4. 鼠标小手的出现

    cursor: pointer;
    

五、聊天室完整前端源码

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>聊天通信</title>
<script src="./utils/jquery.min.js"></script>
<script src="./utils/websocket.js"></script>
<style>
.main_container {
width: 500px;
margin: auto;
}
#msgList {
width: 500px;
height: 400px;
overflow: auto;
border: 2px solid #8491fe;
border-radius: 10px;
padding: 6px;
background-color: #ebffff;
box-sizing: border-box;
}
#msgList::-webkit-scrollbar {
width: 0;
}
.msg_line {
margin: 10px 0;
display: flex;
flex-wrap: wrap;
}
.avatar {
width: 30px;
height: 30px;
border-radius: 50%;
background-color: #77ffff;
text-align: center;
line-height: 30px;
color: #333;
font-size: 12px;
margin-right: 6px;
}
.msg_text {
display: inline-block;
padding: 4px 12px;
border-radius: 6px;
background-color: #f0f1dd;
font-size: 14px;
}
.center_msg {
text-align: center;
color: #f19597;
}
.controls {
width: 100%;
display: flex;
justify-content: space-between;
margin-top: 10px;
}
input {
flex: 1;
outline: none;
height: 34px;
line-height: 34px;
border: 1px solid #d8d8d8;
border-radius: 4px;
padding: 0 4px;
color: #333;
margin-right: 12px;
}
#btn {
width: 80px;
height: 34px;
cursor: pointer;
}
</style>
</head>
<body>
<div class="main_container">

<div id="msgList"></div>

<div class="controls">
<input type="text" class="pushMsg" />
<button id="btn">发送</button>
</div>
</div>
<script src="./utils/websocket.js"></script>
<script>
// 消息列表
const msgList = [];
// 初始化websocket
const newWebSocket = new WebSocketClient('ws:localhost:8080');
newWebSocket.connect();
window.NewWebSocket = newWebSocket;
newWebSocket.addEventListener('message', handleMessage);
// 处理返回数据
function handleMessage(msg) {
const msgData = JSON.parse(msg.data || '{}');
console.log(msgData, "返回数据====");
if (msgData && typeof msgData.msg === 'string' && !msgData.msg.includes('ping')) {
msgList.push({
name: msgData.nickname,
msg: msgData.msg,
});
const str = msgList.reduce((cur, next) => {
let curMsg = '';
if (next.msg.includes('连接')) {
curMsg = `玩家:${next.name}_${next.msg}`;
} else {
curMsg = `
${next.name}
${next.msg}
`;
}
return cur += curMsg;
}, '');
$('#msgList').html(str);
// 获取设置了滚动属性的div标签
const div = document.getElementById('msgList');
// 设置滚动的顶点坐标为滚动的总高度
div.scrollTop = div.scrollHeight;
}
}
// 监听发送按钮
$('#btn').on('click', sendMessage);
// 输入框回车事件
$('.pushMsg').keydown(function(event) {
if (event.key === 'Enter') {
sendMessage();
}
});
// 发送消息
function sendMessage() {
const msg = $('.pushMsg').val();
if (msg) {
newWebSocket.send(`${msg}`);
$('.pushMsg').val('');
}
}
</script>
</body>
</html>
本站无任何商业行为
个人在线分享 » 基于websocket与node搭建简易聊天室
E-->