vue+ts打造一个酷炫的星空聊天室

Easter79 等级 500 0 0

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

项目界面

  vue+ts打造一个酷炫的星空聊天室  

功能介绍


  • 更改用户名/头像上传

  • 群聊/私聊

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

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

  • 表情包

  • 消息分页

技术概览

  • 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 私聊消息表

其中中间表用于建立对于群/好友与用户之间的联系。下面是我画的思维导图,相信大家看完就能理解其中的奥妙啦。
vue+ts打造一个酷炫的星空聊天室

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 {    let userRoom = client.handshake.query.userId;    // 连接默认加入public房间    client.join('public');    // 用户独有消息房间 根据userId    if(userRoom) {      client.join(userRoom);    }    return '连接成功'  }}

  2. 封装全局的中间件,方便在开发过程中调试。

    // middleware.jsexport function logger(req, res, next) {  const { method, path } = req;  console.log(${method} ${path});  next();};// main.js 使用全局中间件app.use(logger)

  3. nestjs 的静态资源配置

    // main.js配置静态资源app.useStaticAssets(join(__dirname, '../public/', 'static'), {  prefix: '/static/', });

  4. nestjs 自定义异常过滤器

    // http-exception.filter.ts@Catch(HttpException)export class HttpExceptionFilter implements ExceptionFilter {  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; // 群主id  groupName: 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.tsconst actions: ActionTree<ChatState, RootState> = {  // 初始化WebSocket  async 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.vueimport { 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


近期

Node在大前端中的应用场景分析

10个Vue开发技巧(下)

vue+ts打造一个酷炫的星空聊天室

若此文有用,何不素质三连❤️

本文分享自微信公众号 - Vue中文社区(vue_fe)。
如有侵权,请联系 support@oschina.cn 删除。
本文参与“OSC源创计划”,欢迎正在阅读的你也加入,一起分享。

收藏
评论区

相关推荐

轻松使用纯css3打造有点意思的故障艺术(附React/Vue加强组件版)
前言 很早之前就看到国外很多酷炫的网站在实践"故障艺术", 或者错位动画", 感觉非常有意思, 现在APP端的抖音启动界面有着这种设计的影子, 作为一名用于探索未知的前端工程师, 有必要好好实践一下这一设计. 正文 接下来笔者将带大家使用纯Css3来实现"故障动画", 并将这一特效封装成React/vue组件, 供大家学习和使用. 先来看看实现的效果:
教你用Python制作炫酷的词云
相信大家也都通过各种渠道了解了老干妈与鹅厂的爱恨纠缠,当然其中还混入了迷惑行为的“骗子”、吃瓜吃得飞起的“阿里系”以及连称此事与我无关的“某搜索引擎”。 不过这是一篇技术文,所以无心管他到底是谁的老千妈,一心只想给大家介绍这个惊艳的好东西。 (https://imghelloworld.osscnbeijing.aliyuncs.com/4
用Python实现武侠小说中的武打动作残影特效
创作背景“飞雪连天射白鹿,笑书神侠倚碧鸳”,相信很多90后知道这副对联的含义,这是武侠小说作家金庸先生的作品合集,说实话在所有的作品中我最喜欢的是倚天屠龙记和天龙八部,应该说基本都喜欢,但是这两部中的爱恨情仇最为突出,倚天屠龙记中周芷若和赵敏,张无忌,再到天龙八部中的乔峰。 说起来武侠小说中的武林高手是真的帅!现在的电影制作技术越来越高超了,武术特效做
100行JS实现HTML5的3D贪吃蛇游戏
[js1k.com](https://www.oschina.net/action/GoToLink?url=http%3A%2F%2Fjs1k.com%2F)收集了小于1k的javascript小例子,里面有很多很炫很酷的游戏和特效,[今年规则](https://www.oschina.net/action/GoToLink?url=http%3A%2F%
IPFS实践之初体验
更多我的博客请关注:[https://kekbin.com/](https://www.oschina.net/action/GoToLink?url=https%3A%2F%2Fkekbin.com%2F) ### 概述 IPFS的全称是InterPlanetary File System(星际文件系统),从名称上看,这是一个很炫酷、很有野心的项目。简
H5酷炫效果
<!doctype html> <html lang="zh-CN"> <head> <meta charset="UTF-8"> <title>线性渐变动画</title> <style> body{ width:100%;
3D页面切换效果
最近看到魅族、小米等官网上面产品介绍页面做的很炫酷,于是找啊找,找到了类似的效果,大家可以看看学校学习,希望对你有用: Demo地址: [http://www.slashie.org/space.js/demo2.html](https://www.oschina.net/action/GoToLink?url=http%3A%2F%2Fwww.slas
10 个非常酷的基于jQuery的菜单效果插件
除了直观的界面效果外,炫酷的网站导航菜单或右键菜单也能为访问者带来眼前一亮的感觉。本文为你带来10个非常酷的基于jQuery的菜单效果插件。  **1.  右击菜单**  一个创建右击菜单的插件,简洁且易用。  ![](http://static.oschina.net/uploads/img/201112/20185535_
10分钟阅读一篇关于Vue
![file](https://oscimg.oschina.net/oscnet/up-4f8ccb1755bb73c4ffe6a7ba91253ddc.jpg "file") Vue-cli Vue脚手架的基本用法,vue脚手架用于快速生成vue项目基础架构: 地址: https://cli.vuejs.org/zh/ 使用方式,安装3.x版本
17、vue
#### 说明: > vue3.0搭建的项目,不过没有引入ts,后来需要用到一个插件是用ts写的,所以vue要用到ts。。。 ### 一、安装typescript及loader > npm install typescript ts-loader --save-dev ![image](https://oscimg.oschina.net/oscne
Android 贝塞尔曲线实战之网易云音乐鲸云特效
作者:哈哈将 -个推 Android 高级开发工程师 **前言** APP开发市场已经告别“野蛮生长”时代,人们不再满足于APP外形创新,而将目光转向全方面的用户体验上。在这过程中,动效化作为移动互联网产品的新趋势,如何实现酷炫丝滑的动画效果已然成为开发者们的新课题。实现方式其实很简单。本文将为你剖析理论基础以及具体应用。咱们日常使用的 APP 的时候,
Color Hunt 漂亮炫酷的配色小程序
利用自己的业余时间,开发了一款颜色配色方案的小程序 - Color Hunt。 小程序主要参考 [Color Hunt](https://www.oschina.net/action/GoToLink?url=https%3A%2F%2Fcolorhunt.co%2F) 这个网站,这个网站设计真的很棒,个人也经常用,所以小程序也秉承网站的风格,没有做调整,
Flutter 实现酷炫的3D效果
![](https://oscimg.oschina.net/oscnet/2a34303ee391c70540d1747e4aa521b0b5e.png) > 老孟导读:此文讲解3个酷炫的3D动画效果。 下面是要实现的效果: ![](https://oscimg.oschina.net/oscnet/cacf46143ca941c8a
TypeScript 中提升幸福感的 10 个高级技巧
![](https://oscimg.oschina.net/oscnet/ec4f1d7b-017a-4d73-bb1a-9d3cd8b5e0ba.png) 用了一年时间的 TypeScript 了,项目中用到的技术是 Vue + TypeScript 的,深感中大型项目中 TypeScript 的必要性,特别是生命周期比较长的大型项目中更应该使用 Ty
vue+ts打造一个酷炫的星空聊天室
😛 闲暇时间想做一个聊天室复盘一下这些年学习到的技术,于是在2020年6月24号就开始了 Genal 聊天室的开发之旅。 😈 项目采用全 typescript 开发,这是为了以后的功能迭代打基础。当然,我本身也是很喜欢 typescript 的。 项目界面 ----   ![](https://oscimg.o