该项目是用Vue实现的一个多帐号多对象的聊天室项目,初期希望的是划分组件的同时可以将逻辑也进行划分,通过这样的方式来减小每个组件的复杂度。但是后来发现几乎所有的逻辑,都是围绕着从服务端拉取到的消息来进行的,如果强行分割逻辑,只会增加代码的复杂度。

组件划分

  • Wrap
    • UserList
    • RoomList
    • ChatWindow
      • MessageItem
      • EmoticonSelector

这里将组件划分为用户列表UserList、聊天列表RoomList、聊天窗口ChatWindow。

组件参数及事件

UserList

Props:

  • users:帐号
  • current:当前帐号
  • unreadInfo:用于展示未读标记

Events:

  • changeUser:切换用户

RoomList

Props:

  • rooms:聊天室
  • current:当前聊天室
  • roomsInfo:聊天室未读数、开始时间、最新时间、最新消息、状态等

Events:

  • changeRoom

EmoticonSelector

Props:

  • emoticons

Events:

  • select

MessageItem

Props:

  • user:当前帐号
  • other:聊天对象
  • message:消息
  • roomStatus:聊天室状态*

Events:

ChatWindow

Props:

  • user:当前帐号
  • room:当前聊天室
  • messages:当前聊天室消息
  • roomsInfo:聊天室未读数、开始时间、最新时间、分数、最新消息、状态

Events:

  • send:发送消息

基本设计思路

行为一:获取到消息(我们的后端拉取消息是根据帐号拉取的)

Wrap中不停(标记messagePolling)拉取每个帐号(activeActors)消息messages

  • => messages根据roomId保存localStorage
  • => 存在roomId不在房间(roomIds)中 => 拉取该用户rooms*
  • => messages中有当前帐号(currActor)的消息 => 重新排列聊天室(roomList)*
  • => messages中有当前聊天室(currRoom)的消息 => 重新计算当前聊天室消息(messageList)
  • => 计算房间未读等信息(roomsInfo)
  • => 计算帐号未读信息(unreadByActor)

行为二:发送消息

ChatWindow触发send

  • => 将消息保存到localStorage中
  • => 重新设置当前聊天室消息(messageList)
  • => 重新排列聊天室(roomList)

行为三:切换帐号

UserList触发changeUser

  • => 重新计算聊天室(roomList)通过(rooms)和(currActor) => 重新排列聊天室(roomList)* => 重新设置当前聊天室(currRoom) => 重新设置当前聊天消息(messageList)
  • => 计算房间未读等信息(roomsInfo)
  • => 计算帐号未读信息(unreadByActor)

在实际代码中,计算unreadByActor依赖roomsInfo;计算messageList,依赖将消息保存localStorage。

值得一提

async/await“同时”请求:通过await Promise.all可以将请求异步,后面的代码继续同步执行,需要注意的是Promise.all中的promise需要自己处理自己的异常,这样来避免异常提早将Promise.all拒绝。