所用技术
- socket.io
socket.io是在websocket上进行了一层封装,让websocket变得更好用。 - express
Express 是一个简洁而灵活的 node.js Web应用框架, 提供了一系列强大特性帮助你创建各种 Web 应用,和丰富的 HTTP 工具。使用 Express 可以快速地搭建一个完整功能的网站。 - node.js
首先,Nodejs 是基于 Chrome 的 V8 引擎开发的一个 C++ 程序,目的是提供一个 JS 的运行环境。最早 Nodejs 主要是安装在服务器上,辅助大家用 JS 开发高性能服务器代码,但是后来 Nodejs 在前端也大放异彩,带来了 Web 前端开发的革命。Nodejs 下运行 JS 代码有两种方式,一种是在 Node.js 的交互环境下运行,另外一种是把代码写入文件中,然后用 node 命令执行文件代码。Nodejs 跟浏览器是不同的环境,写 JS 代码的时候要注意这些差异。最后,我们介绍了 npm ,通过 npm 装包的方式,开发中我们再也不用重造轮子了。
用例图
具体实现
前端
选择头像和用户名
// 选择头像事件
$('.avatrs .avatr').click(function () {
$(this).addClass('active').siblings().removeClass('active');
})
// 点击登录
$('.goChat').click(function () {
// 获取用户名
const username = $('.login_name').val().trim();
if (username === '') {
alert('请输入用户名!');
return;
}
// 获取头像
let avatar = $('.avatrs .active').css('background-image').split("\"")[1];
avatar = avatar.slice(22);
avatar = './' + avatar;
socket.emit('login', {
username,
avatar
});
})
登陆验证
// 登录失败
socket.on('loginError', (data) => {
alert(data.message)
})
// 登录成功
socket.on('loginSuccess', (data) => {
$('.login').css('display', 'none')
$('.out').css('display', 'flex')
// 设置自己的头像和用户名
$('.left .top .avatr').css('background-image', 'url("' + data.avatar + '")');
$('.loginSucc_name').text(data.username);
// 将全局的username和avatar重新赋值
username = data.username;
avatar = data.avatar;
})
登录和退出提醒
// 设置加入聊天的信息
socket.on('addUser', (data) => {
const message = ` <div class="message">"${data.username}" 加入了群聊</div>`;
$('.chat').append(message);
})
// 设置用户列表刷新
socket.on('updateList', (data) => {
// 先清空列表再遍历,防止用户列表出现重复用户
$('.list').html('');
// 设置总列表用户
data.forEach(item => {
let child = ` <li>
<div class="avatr" style="background-image: url('${item.avatar}'); background-size: cover;"></div>
<span> ${item.username}</span>
</li>`;
$('.list').append(child);
});
// 设置聊天室总人数
$('.right_top').text(`聊天室(${data.length})`);
})
// 设置退出聊天事件
socket.on('loginOut', (data) => {
console.log(data);
// 设置加入聊天的信息
const message = ` <div class="message">"${data.username}" 退出了群聊</div>`;
$('.chat').append(message);
})
发送信息
// 设置发送信息事件
$('.send').click(function () {
// 获取消息
const content = $('.message_content').val().trim();
if (content == '') {
alert('发送的消息不能为空!');
return;
}
// 向socket发送 trigger_send事件,带上 发送的内容 以及 当事人名字 和 头像
socket.emit('trigger_send', { content, username, avatar });
})
// 发送消息
socket.on('send', (data) => {
let message;
// 自己发的消息
if (username === data.username) {
message = ` <div class="self">
<div class="avatr" style="background-image: url('${data.avatar}'); background-size: cover;"></div>
<div class="username">${data.username}</div>
<div class="content" style="background-color: rgb(22, 170, 22); color:white">${data.content}</div>
</div>`;
} else {
// 别人发的消息
message = ` <div class="user">
<div class="avatr" style="background-image: url('${data.avatar}'); background-size: cover;"></div>
<div class="username">${data.username}</div>
<div class="content">${data.content}</div>
</div>`;
}
// 添加消息
$('.chat').append(message);
// 清空输入内容
$('.message_content').val('');
// 滚动到最下面
$('.chat').children(':last')[0].scrollIntoView();
})
后端
创建服务器同时创建socket.io对象
var app = require('express')();
var server = require('http').Server(app);
var io = require('socket.io')(server);
监听是否有客户端连接
注意此处是通过express建立服务器后台框架
server.listen(3000, () => {
console.log('成功建立连接');
});
这里通过express配置前端资源URL路径
app.use(require('express').static('public'));
app.get('/', function (req, res) {
res.sendfile(__dirname + '/index.html');
});
处理登录事件
// 处理登录事件
socket.on('login', (data) => {
// 查找是否重复登录
let res = users.find(item => item.username === data.username)
if (res) {
socket.emit('loginError', { message: '用户已登录!不能重复登录' })
} else {
// 为socket对象添加当前用户标识
socket.username = data.username;
socket.avatar = data.avatar;
// 添加到总用户中
users.push(data);
// 个人事件
socket.emit('loginSuccess', data);
// 广播加入聊天事件
io.emit('addUser', data);
// 重新设置列表人数
io.emit('updateList', users);
}
});
处理用户退出事件
// 监听退出连接事件
socket.on('disconnect', () => {
// 查找退出登录的用户索引
const i = users.findIndex(item => item.username === socket.username);
// 发送广播退出聊天事件
io.emit('loginOut', users[i]);
// 删除该用户
users.splice(i, 1);
// 重新设置列表人数
io.emit('updateList', users);
})
有用户发送消息
// 设置发送信息聊天事件
socket.on('trigger_send', (data) => {
// 广播 触发 发送消息
io.emit('send', data);
})