作者:edisonC

原文地址:https://juejin.im/post/6854573222415826957

简介

???? 闲暇时间想做一个聊天室复盘一下这些年学习到的技术,于是在2020年6月24号就开始了 Genal 聊天室的开发之旅。
???? 项目采用全 typescript 开发,这是为了以后的功能迭代打基础。当然,我本身也是很喜欢 typescript 的。

项目界面

功能介绍

  • 更改用户名/头像上传

  • 群聊/私聊

  • 创建群/加入群聊/模糊搜索群

  • 添加好友/模糊搜索好友

  • 表情包

  • 消息分页

技术概览

  • Typescript:JavaScript 的一个超集,它最大的优势是提供了类型系统和提高了代码的可读性和可维护性。

  • Vue2.6.x:前端渐进式框架。

  • Socket/io:实现实时通信,websocket 第三方库。

  • Vuex:专为 Vue.js 应用程序开发的状态管理模式。

  • Nestjs:是一个用于构建高效、可扩展的 Node.js 服务端应用框架,基于 TypeScript 编写并且结合了 OOP1、FP2、FRP3 的相关理念。

  • Typeorm: 支持最新的 JavaScript 特性并提供额外的特性以帮助你开发任何使用数据库的应用程序。

  • ES6+:采用 ES6+ 语法,箭头函数、async/await 等等语法很好用。

  • SASS(SCSS):用 SCSS 做 CSS 预处理语言,可以使用最高效的方式,以少量的代码创建复杂的设计。

数据库表结构设计

数据库使用了六张表,分别是

  • user 用户表

  • group 群表

  • user_group 用户_群中间表

  • group_message 群消息表

  • user_friend 用户_好友中间表

  • friend_message 私聊消息表

其中中间表用于建立对于群/好友与用户之间的联系。下面是我画的思维导图,相信大家看完就能理解其中的奥妙啦。

WebSocket的建立逻辑

用户房间的建立

每个用户进入聊天室都会自动加入名为 public 的 WebSocket 房间和以用户 id 为命名的 WebSocket 房间,其中建立用户房间是为了方便系统针对用户单独广播事件。如果不了解房间的概念,可以认为只有房间内的人才能接收到房间内的广播,更多信息请移步 socket.io 官网。

群聊房间的建立

以 groupId 作为 WebSocket 房间的名字,每次有新用户加入群都会在群房间内广播用户进群事件并附带上新用户的详细信息,然后其他用户会存储新用户的信息。当新用户发消息的时候,其他用户收到消息后可以通过消息的userId找到对应用户的详细信息。这样能保证消息发出后其他用户能够快速知道消息的主人.

私聊房间的建立

每当发起一个添加好友的请求,就会把用户的 userId 和好友的 userId 拼接成的字符串作为 WebSocket 的房间名,从而建立私聊房间。

后端架构

后端使用了 nestjs 这个近几年发展迅猛的 node.js 框架。nestjs 的优势有很多, 我只列举出以下几点:

  1. 基于 TypeScript 构建,同时兼容普通的 ES6。

  2. nestjs 的依赖注入以及模块化的思想,使得代码结构清晰,便于维护。

  3. nestjs 的 @nestjs/websockets 包封装好了对于 WebSocket 事件的处理,对于开发聊天室有优势。

下面是一些后端的逻辑代码。

  1. 使用 nestjs 建立 WebSocket 连接

// chat.gateway.ts
@WebSocketGateway()
export class ChatGateway {// socket连接钩子async handleConnection(client: Socket): Promise<string> {let userRoom = client.handshake.query.userId;// 连接默认加入public房间client.join('public');// 用户独有消息房间 根据userIdif(userRoom) {client.join(userRoom);}return '连接成功'}
}
  1. 封装全局的中间件,方便在开发过程中调试。

// middleware.js
export function logger(req, res, next) {const { method, path } = req;console.log(`${method} ${path}`);next();
};// main.js
使用全局中间件
app.use(logger)
  1. nestjs 的静态资源配置

// main.js
配置静态资源
app.useStaticAssets(join(__dirname, '../public/', 'static'), {prefix: '/static/',
});
  1. nestjs 自定义异常过滤器

// http-exception.filter.ts
@Catch(HttpException)
export class HttpExceptionFilter implements ExceptionFilter<HttpException> {catch(exception: HttpException, host: ArgumentsHost) {const ctx = host.switchToHttp();const response = ctx.getResponse();const request = ctx.getRequest();const status = exception.getStatus();const exceptionRes: any = exception.getResponse();const {error,message,} = exceptionRes;// 以下格式将在发生错误是返回给前端response.status(status).json({status,timestamp: new Date().toISOString(),path: request.url,error,message,});}
}

前端架构

页面初始化

初始化会调起 WebSocket 连接函数,然后拿到用户所有的群信息和所有的好友信息,再通过建立 WebSocket 通信的规则加入到对应的房间,然后使用 vuex 派发最新的数据。

数据处理

群的数据类型

// 群组
interface Group {groupId: string;userId: string; // 群主idgroupName: string;notice: string;messages: GroupMessage[];createTime: number;
}

好友的数据类型

// 好友
interface Friend {userId: string;username: string;avatar: string;role?: string;tag?: string;messages: FriendMessage[];createTime: number;
}

我曾经用对象数组 [ friend1 , friend2 ... ] 这样的结构去管理所有的 群/好友 数据,但是当数据量很大的时候,查询和更新 群/好友 数据会变得很消耗性能。每次好友名字变了或者头像变了就得遍历查找一遍数组才能更新相应信息。
后来我用对象的结构,优化了聊天室的代码。我使用一个对象 gather 来管理 群/好友 的信息, gather 的键为 groupId/userId ,值为对应的 群/好友 的数据,结构如下

gather = {'userId': {userId: 'userId'username: 'xxx'messages: [];...}
}

每个群和用户都有独一无二的 id,所以无需担心重复。使用这样的结构后,更新数据便非常的轻松,只需要拿到需要更新的id,然后直接覆盖 gather.id 对应的值就行了

vuex

聊天室涉及到数据的即时更新和各个 vue 组件的数据同步,处理这样的业务场景是 vuex 的强项。我把建立 WebSocket 连接的函数写在了 vuex 的 action 中,在用户登录成功后调起连接函数,下面是精简后的代码。

// actions.ts
const actions: ActionTree<ChatState, RootState> = {// 初始化WebSocketasync connectSocket({commit, state, dispatch, rootState}, callback) {// WebSocket连接建立socket.on('connect', async () => {// 订阅群消息时间socket.on('groupMessage', (res: any) => {console.log('on groupMessage', res)if (!res.code) {// 对群消息进行处理commit(ADD_GROUP_MESSAGE, res.data)}})}}

不得不说 vuex-class 这个库帮了我很大的忙,它是 vuex 结合 typescript 开发的很好的粘合剂。使用了 vuex-class ,那么在 vue 组件中调用 vuex 的方法只需要这么写:

// GenalChat.vue
import { namespace } from 'vuex-class'
const appModule = namespace('app')
export default class GenalChat extends Vue {@appModule.Getter('user') user: User;@appModule.Action('login') login: Function;
}

总结

  目前聊天室已经完成日常聊天的基础功能,因为聊天室的数据结构基本都大同小异,因此目前的聊天室架构是非常利于在此基础上进行扩展和新增功能的。同时,我今后也会陆续开发很多酷炫的功能,喜欢的朋友给个 star 鼓励一下我吧!

项目地址

github:https://github.com/genaller/genal-chat

nestjs+vue+ts打造一个酷炫的星空聊天室(含完整数据库设计)相关推荐

  1. 【有利可图网】PS实战教程52:巧用PS设计打造一个酷炫的喷溅海报特效!

    本篇教大家如何巧用PS设计打造一个酷炫的喷溅海报特效教学!教程主要是运用到了蒙版和笔刷技巧,学习掌握,可以灵活运用到其它设计中,感兴趣的童鞋赶快收走试试看,需转学起来吧!

  2. 肝了一夜!我用Python打造了一款武林外传QQ聊天室

    公众号 "菜鸟学Python" 第439篇原创,设为 "星标",一起学Python! 大家在平时的学习或者是生活中,想必都少不了群聊,无论是微信还是QQ,都有群 ...

  3. 用个人博客打造一个酷酷的工作流

    用个人博客打造一个酷酷的工作流! 每个前端都应该拥有一个自己的博客.因为它不仅仅是一个博客.更是属于自己的一个工作流.如何来理解这个问题呢.这也就是我要开发一个博客的初衷. 似乎自己也没有一个写博客的 ...

  4. python随手记自动记账_菜鸟也疯狂!8分钟用Python做一个酷炫的家庭随手记

    原标题:菜鸟也疯狂!8分钟用Python做一个酷炫的家庭随手记 每个月都有各种各样的开销,不当家不知道柴米贵呀!柴米油盐酱醋茶样样都要开销,吃的穿的,各种开销,每个月都没有啥结余,小编月初是富人,月底 ...

  5. 分享给你一个酷炫的前端组件库,还不用起来?

    fancy-components 一个酷炫的前端组件库 大伙前端都是用什么组件库的呢? 我最近刚发现前端一个很好看.很炫酷的组件库.那就是fancy-components ,简直是"酷炫&q ...

  6. 使用TextInputLayout分分钟构造一个酷炫登录框架

    Google在2015的IO大会上,给我们带来了更加详细的Material Design设计规范,同时,也给我们带来了全新的Android Design Support Library,Android ...

  7. 利用GitHub搭建一个酷炫免费的个人博客

    转载自公众号:python_shequ 由于公众号的文章不易后续整理阅读,于是小吴昨天上午花了半个小时使用 GitHub + Hexo 搭建了一下个人博客,打算将公众号的文章搬过去,支持关键字搜索.分 ...

  8. 超详细——手把手教你用threejs实现一个酷炫的模型发光扫描效果(一)

    前言 模型特效是大家在3d可视化项目所追求的,但很多人苦于无法实现一个好的模型效果,本次就手把手一步一步教你实现一个酷炫的模型发光扫描特效,帮让你的项目提升一个逼格.话不多说,先上效果: 本文所使用的 ...

  9. 如何开发一个酷炫的mdx

    使用mdx开发一个酷炫的ppt ​ 效果展示:mdx-deck-slide-decks MDX 是一种书写格式,允许你在 Markdown 文档中无缝地插入 JSX 代码. 你还可以导入(import ...

  10. 【有了可图网】PS实战系列64:用PS的3D功能设计制作一个酷炫的彩色立体字体

    本篇教大家如何巧用PS的3D功能设计制作一个酷炫的彩色立体字体!教程讲解过程超详细,主要用到了PS的滤镜.调整层以及图层样式来完成效果,需转学起来! 彩色立体文字纹理素材链接链接:https://pa ...

最新文章

  1. java事务设计iofo,Spring事务最佳实践
  2. 湖南大学计算机与通信学院研究生,湖南大学计算机与通信学院2010年硕士研究生招生学科...
  3. 前端遇上Go: 静态资源增量更新的新实践
  4. 【计算机语言】C语言小游戏——贪吃蛇
  5. jQuery 滚动条插件nicescroll 使用方法、常见配置和事件回调使用说明
  6. PMP考试知识总结【精华--持续更新】
  7. 常用网络拓扑在网络规划设计中
  8. word批量替换向下箭头为回车符号、批量删除空行、批量空格与空行
  9. 极速办公(Excel)如何方框内打勾
  10. CAN总线技术2--CAN网络控制芯片SJA1000
  11. DotSoft.C3DTools.v7.0.0.3民用勘测地图和GIS工具集合
  12. 清理数据 python_使用python的数据清理技术
  13. UVM糖果爱好者教程 - 31.provides_responses?
  14. EXCEL表格序列号
  15. 微信蓝牙设备服务器,微信又更新了 支持连接蓝牙设备
  16. 美国计算机专业修什么课程,美国计算机研究生需要的先修课程有哪些?
  17. 数字金字塔(保证两位数的数字也能排好)
  18. web项目-中日韩文通用UTF-8处理流程
  19. 数据结构(严蔚敏版)习题集第三章课后标新号习题答案
  20. 惠普179fnw打印机使用说明_惠普HP Color Laser MFP 179fnw一体机驱动

热门文章

  1. Cisco Packet Tracer vty的两种接口
  2. 针式PKM适合对“大量的资料”进行系统性管理
  3. opencv-python——基于标志物的道路逆透视变换
  4. 十大推荐提交的安卓市场
  5. 根据经纬度获取地址(逆地址解析)
  6. <论文阅读> DI-FODO — 3D距离传感器的快速视觉里程计
  7. python爬虫爬取拉勾网招聘信息
  8. 毕业设计-基于深度学习的视频目标检测
  9. Math三点共线判断
  10. Intel Centrino 2 vPro平台上的Intel AMT 4.0技术相关资源