我开始这个项目是因为我有兴趣学习如何使用 websockets。我还找到了各种后台模板,但没有一个能满足我的要求。所以我决定研究如何创建一个简单的即时聊天后台。我测试了两种方案:第一种是使用 Socket.io 和 Node.js,第二种是使用 Socket.io 和 MongoDB 来存储消息历史记录。本文将讨论第一种方案。
前端
首先创建了一个简单的 “登录 “页面,供用户输入用户名并加入聊天。具体步骤如下:
1. 创建一个 “client”文件夹,在 VSCode 中打开它,然后在 client 文件夹中运行 npm init
命令来初始化项目。
2. 创建一个 “index.html “文件。
3. 在 “package.json “中添加以下命令以启动项目:
“scripts”: {
"run": "index.html"
}
4. 创建 “style.css “和 “main.js”。为了节省时间,我使用了 Bootstrap 来创建样式。
5. 将文件链接到 “index.html “文件,并包含 Bootstrap。
6. 为登录页面创建 HTML 结构:
<div id="login-container" class="container justify-content-center align-items-center">
<div class="login-wrapper w-100">
<form id="login" class="d-flex flex-column align-items-center w-100">
<h2 class="hedline-login">Log In to Chat</h2>
<input id="username" class="form-control w-50" type="text">
<button class="btn btn-outline-info btn-lg w-50" type="submit">Log In</button>
</form>
</div>
</div>
和聊天页面:
<div id="chat-container" class="container hidden">
<div class="wrapper d-flex flex-column justify-content-between w-100">
<ul id="message-container">
</ul>
<form class="message-form__container d-flex align-items-center w-100" id="message-form" action="" method="">
<textarea class="textarea-form" id="message-input" cols="2" rows="3"></textarea>
<button class="btn btn-outline-info btn-lg" type="submit">Send</button>
</form>
</div>
</div>
7. 在 “index.html “文件中链接 Socket.io 库:
<script src=”http://localhost:5000/socket.io/socket.io.js"></script>
JavaScript 代码:
1. 使用服务器 URL 初始化 Socket.io:
const socket = io (' http : //localhost:5000');
2. 获取登录表单、消息输入、消息容器以及登录和聊天容器的元素:
const messageContainer = document.getElementById(‘message-container’);
const messageForm = document.getElementById(‘message-form’);
const messageInput = document.getElementById(‘message-input’);
const loginContainer = document.getElementById(‘login-container’);
const chatContainer = document.getElementById(‘chat-container’);
const loginFrom = document.getElementById(‘login’);
const usernameEl = document.getElementById(‘username’);
let username = ‘’;
3. 为来自用户和系统的信息定义类别:
const msgFromMeClass = 'message - from-me';
const msgSystemClass = 'message - system';
4. 设置事件监听器,处理用户登录时提交的表单:
loginFrom.addEventListener('submit', e =>{
});
5. 阻止默认表单提交行为:
loginFrom.addEventListener('submit', e =>{
e.preventDefault();
});
6. 从输入框中获取用户名:
loginFrom.addEventListener('submit', e =>{
e.preventDefault();
username = usernameEl.value;
});
7. 发出“new-user”事件以通知服务器有关新用户的信息:
loginFrom.addEventListener('submit', e =>{
e.preventDefault();
username = usernameEl.value;
socket.emit('new-user', username);
});
8. 更新显示状态,从登录状态切换到聊天状态:
在 style.css 中创建了一个类,名为 “hidden”,内含 “display: none;”。
loginFrom.addEventListener('submit', e =>{
e.preventDefault();
username = usernameEl.value;
socket.emit('new-user', username);
loginContainer.classList.add('hidden');
chatContainer.classList.remove('hidden');
});
9. 处理“user-connected”事件,通知其他用户新用户的连接情况:
loginFrom.addEventListener('submit', e =>{
e.preventDefault();
username = usernameEl.value;
socket.emit('new-user', username);
loginContainer.classList.add('hidden');
chatContainer.classList.remove('hidden');
socket.on('user-connected', user => {
});
});
10. 创建渲染聊天消息和系统消息的函数:
function renderMessage(from, message, className){
messageContainer.innerHTML += `
<li class="${className}">
<div class="message">
<span class="author" style="font-size: 70%;">${from}</span>
<span class="message-text">${message}</span>
</div>
</li>
`;
}
11. 监听传入的聊天信息,并使用渲染功能显示它们:
因此,我将其称为 “from”,即我们的消息正文。它可以是来自用户的消息,也可以是系统消息,如 “用户名已连接”。
className:设置来自我和用户的消息的样式。
12. 置使用“Enter”键或单击按钮发送聊天消息的处理程序:
messageForm.addEventListener('submit', handleSubmit);
messageInput.addEventListener('keydown', handleSubmit);
function handleSubmit(e) {
if (e.key === 'Enter' || e.type === 'submit') {
e.preventDefault();
const message = messageInput.value;
if (!message.trim()) return;
socket.emit('send-chat-message', message);
messageInput.value = '';
}
}
13. 包含基本验证以防止发送空消息:
if (!message.trim ( )) return ;
14. 向服务器发出“send-chat-message”事件:
socket.emit('send-chat-message', message);
15. 处理“chat-message”事件以显示传入的聊天消息:
socket.on('chat-message', data => {
const addingClass = username === data.username ? msgFromMeClass : '';
renderMessage(data.username, data.message, addingClass);
});
16. 收到新消息时,在聊天容器中添加自动滚动功能:
messageContainer.scrollTop = messageContainer.scrollHeight;
完整代码:
function renderMessage(from, message, className){
messageContainer.innerHTML += `
<li class="${className}">
<div class="message">
<span class="author" style="font-size: 70%;">${from}</span>
<span class="message-text">${message}</span>
</div>
</li>
`;
messageContainer.scrollTop = messageContainer.scrollHeight;
}
17. 以相同的方式创建断开连接:
socket.on('user-disconnected', username => {
renderMessage('SYSTEM', `${username} disconnected`, msgSystemClass)
});
后台
1. 创建 “服务器 “文件夹。
2. 使用 npm init
初始化项目。
3. 创建一个 “index.js “文件。
4. 安装 Socket.io 和 Express.js 软件包:
npm install socket.io
npm install express
5. 导入Socket.io模块:
import { Server } from 'socket.io';
6. 创建一个对象来存储用户数据:
const users = {};
7. 设置 CORS(跨来源资源共享),允许所有来源:
npm install cors
8. 创建 Socket.IO 服务器并将其绑定到 5000 端口:
const io = new Server(5000, {
cors: {
origin: '*',
}
});
9. 处理用户连接:
io.on('connection', (socket) => {
socket.on('new-user', username => {
users[socket.id] = username;
socket.emit('user-connected', username);
socket.broadcast.emit('user-connected', username);
});
});
10. 发布事件,通知用户新连接、断开连接和聊天信息:
socket.on('send-chat-message', (message) => {
socket.emit('chat-message', { message: message, username: users[socket.id] })
socket.broadcast.emit('chat-message', { message: message, username: users[socket.id] })
});
socket.on('disconnect', () => {
socket.broadcast.emit('user-disconnected', users[socket.id])
delete users[socket.id]
});
此代码的完整版本如下所示:
io.on('connection', (socket) => {
socket.on('new-user', username => {
users[socket.id] = username;
socket.emit('user-connected', username);
socket.broadcast.emit('user-connected', username);
});
socket.on('send-chat-message', (message) => {
socket.emit('chat-message', { message: message, username: users[socket.id] })
socket.broadcast.emit('chat-message', { message: message, username: users[socket.id] })
});
socket.on('disconnect', () => {
socket.broadcast.emit('user-disconnected', users[socket.id])
delete users[socket.id]
});
});
最后为 HTML 元素应用样式。源代码地址:https://github.com/soyUnaGata/real-time-chat.git
使用 MongoDB 的第二部分即将推出。
作者:unaGataProgrammer
本文来自作者投稿,版权归原作者所有。如需转载,请注明出处:https://www.nxrte.com/jishu/im/37544.html