前言:最近在学习Redux+react+Router+Nodejs全栈开发高级课程,这里对实践过程作个记录,方便自己和大家翻阅。最终成果github地址:https://github.com/66Web/react-antd-zhaoping,欢迎star。


一、聊天信息根据用户分组

  • 从redux中获取到chatmsg:其中包含了所有与当前用户有关的聊天信息
  • 与不同的用户聊天信息的chatid不同:根据chatid可将数据分到不同的数组

    1. //按照聊天用户分组,根据 chatid
    2. const msgGroup = {}
    3. this.props.chat.chatmsg.forEach(v=>{
    4. msgGroup[v.chatid] = msgGroup[v.chatid] || []
    5. msgGroup[v.chatid].push(v)
    6. })
  • Object.values():返回数组,成员是参数对象自身的(不含继承的)所有可遍历(enumerable)属性的键名

  • 将分好组的聊天信息,通过Object.values()获得新的二维数组

    1. const chatList = Object.values(msgGroup)  

二、聊天列表展示

  • 获取【最后一条聊天信息】
  1. 定义一个方法返回数组的最后一个值:每个用户的聊天信息自动按照create_time排序,最后即最新

    1. getLast = (arr) => {
    2. return arr[arr.length-1]
    3. }
  2. 遍历用户信息二维数组,获得每一个用户的聊天信息数组,调用方法获取最后一条信息

    1. {chatList.map(v=>{
    2. // console.log(v)
    3. const lastItem = this.getLast(v)   
  • 获取【对方用户】的用户名及头像
  1. 从redux中获取到当前用户的userid,以及存储所有用户name和avatar的userinfo
  2. 遍历获得每一个用户的聊天信息数组后,判断聊天信息的from是否为当前userid,如果是则将to赋给targetId,否则赋from
    1. const Item = List.Item
    2. const Brief = Item.Brief
    3. const userid = this.props.user._id
    4. const userinfo = this.props.chat.users
    5.  
    6. //其它代码
    7. const targetId = v[0].from==userid?v[0].to:v[0].from
    8. return (
    9. <List key={lastItem._id}>
    10. <Item
    11. thumb={require(`../img/${userinfo[targetId].avatar}.png`)}
    12. arrow="horizontal"
    13. onClick={()=>{
    14. this.props.history.push(`/chat/${targetId}`)
    15. }}
    16. >
    17. {lastItem.content}
    18. <Brief>{userinfo[targetId].name}</Brief>
    19. </Item>
    20. </List>
    21. )
  • 获取【未读消息数】:过滤显示read为false,且to时当前用户userid的聊天信息数组的length数

    1. const unreadNum = v.filter(v=>!v.read&&v.to==userid).length
    2.  
    3. extra={<Badge text={unreadNum}></Badge>}

      

三、最新消息排序

  • 给二维数组进行排序:比较不同用户聊天信息的最后一条的create_time,最大者最新,优先显示

    1. //用户信息数组的数组、排序
    2. const chatList = Object.values(msgGroup).sort((a, b)=>{
    3. const a_last = this.getLast(a).create_time
    4. const b_last = this.getLast(b).create_time
    5. return b_last - a_last
    6. })

      

四、消息未读数更新

  • 获取当前聊天的目标用户【to】,发送给后端更新数据库中的未读消息
  1. chat.js中:为了在当前打开的聊天页面中【伪同步】标识消息已读,在componentWillUnmount时更新消息

    1. componentWillUnmount(){
    2. const to = this.props.match.params.user
    3. this.props.readMsg(to)
    4. }  
  2. chat.redux.js中:定义readMsg(from),通过axios.post发送请求,将目标用户的userid【to】传给后端(更新条件:聊天信息中只有from为【to】,即目标用户发来的才算未读)

    1. //操作数据的方法
    2. export function readMsg(from){
    3. return (dispatch, getState)=>{
    4. axios.post('/user/readmsg',{from})
    5. .then(res=>{
    6. console.log(res)
    7. })
    8. }
    9. }
  • user.js中:处理标识已读的后端请求/readmsg,更新数据库中的聊天信息

  1. 更新条件一:聊天信息的to为当前用户的userid,从req.cookies中获取到

  2. 更新条件二:聊天信息的from为目标用户的userid,从req.body中获取到

  3. 满足条件时:将聊天信息的read字段,设置为true,标识已读

  4. mongodb的更新操作默认只更新第一条,设置{'multi':true}可同时更新多条

  5. 更新成功后:返回更新成功的数据条数doc.nModified

    1. //标识已读
    2. Router.post('/readmsg', function(req, res){
    3. const userid = req.cookies.userid
    4. const {from} = req.body
    5. console.log(userid, from)
    6. Chat.update({from, to:userid},
    7. {'$set':{read:true}},
    8. {'multi':true},function(err, doc){
    9. if(!err){
    10. return res.json({code:0, num:doc.nModified})
    11. }
    12. return res.json({code:1, msg:'修改失败'})
    13. })
    14. })

  • chat.redux.js中:将数据库中标识已读之后的聊天信息数据存入redux中

    1. //action type
    2. const MSG_READ = 'MSG_READ' //标识已读
    3.  
    4. //reducer中:只标识当前用户与目标用户的聊天信息中from为目标用户的信息
    5. case MSG_READ:
    6. const {from, num} = action.payload
    7. return {...state, chatmsg:state.chatmsg.map(v=>({...v, read:from==v.from?true:v.read})) , unread:state.unread-num}
    8.  
    9. //action creator
    10. function msgRead({from, to, num}){
    11. return {type:MSG_READ, payload:{from, to, num}}
    12. }
    13.  
    14. //readMsg方法中:成功获取后端返回的数据后,触发action将数据存入redux
    15. axios.post('/user/readmsg',{from})
    16. .then(res=>{
    17. const userid = getState().user._id
    18. if(res.status==200&&res.data.code==0){
    19. dispatch(msgRead({userid, from, num:res.data.num}))
    20. }
    21. })

注:项目来自慕课网

【招聘App】—— React/Nodejs/MongoDB全栈项目:消息列表的更多相关文章

  1. 【招聘App】—— React/Nodejs/MongoDB全栈项目:登录注册

    前言:最近在学习Redux+react+Router+Nodejs全栈开发高级课程,这里对实践过程作个记录,方便自己和大家翻阅.最终成果github地址:https://github.com/66We ...

  2. 【招聘App】—— React/Nodejs/MongoDB全栈项目:socket.io&聊天实现

    前言:最近在学习Redux+react+Router+Nodejs全栈开发高级课程,这里对实践过程作个记录,方便自己和大家翻阅.最终成果github地址:https://github.com/66We ...

  3. 【招聘App】—— React/Nodejs/MongoDB全栈项目:信息完善&用户列表

    前言:最近在学习Redux+react+Router+Nodejs全栈开发高级课程,这里对实践过程作个记录,方便自己和大家翻阅.最终成果github地址:https://github.com/66We ...

  4. 【招聘App】—— React/Nodejs/MongoDB全栈项目:项目准备

    前言:最近在学习Redux+react+Router+Nodejs全栈开发高级课程,这里对实践过程作个记录,方便自己和大家翻阅.最终成果github地址:https://github.com/66We ...

  5. 【招聘App】—— React/Nodejs/MongoDB全栈项目:个人中心&退出登录

    前言:最近在学习Redux+react+Router+Nodejs全栈开发高级课程,这里对实践过程作个记录,方便自己和大家翻阅.最终成果github地址:https://github.com/66We ...

  6. 全栈项目|小书架|服务器端-NodeJS+Koa2实现首页图书列表接口

    通过上篇文章 全栈项目|小书架|微信小程序-首页水平轮播实现 我们实现了前端(小程序)效果图的展示,这篇文章来介绍服务器端的实现. 首页书籍信息 先来回顾一下首页书籍都有哪些信息: 从下面的图片可以看 ...

  7. 全栈项目|小书架|服务器端-NodeJS+Koa2 实现书籍详情接口

    通过上篇文章 全栈项目|小书架|微信小程序-首页水平轮播实现 我们实现了前端(小程序)效果图的展示,这篇文章来介绍服务器端的实现. 书籍详情分析 书籍详情页面如下: 从上图可以分析出详情页面大概有以下 ...

  8. 全栈项目|小书架|服务器开发-NodeJS 使用 JWT 实现登录认证

    通过这篇 全栈项目|小书架|服务器开发-JWT 详解 文章我们对JWT有了深入的了解,那么接下来介绍JWT如何在项目中使用. 安装 $ npm install jsonwebtoken 生成 Toke ...

  9. Vue、Node全栈项目~面向小白的博客系统~

    个人博客系统 前言 ❝ 代码质量问题轻点喷(去年才学的前端),有啥建议欢迎联系我,联系方式见最下方,感谢! 页面有啥bug也可以反馈给我,感谢! 这是一套包含前后端代码的个人博客系统,欢迎各位提出建议 ...

随机推荐

  1. Linux内核态抢占机制分析【转】

    转自:http://blog.csdn.net/yiyeguzhou100/article/details/53097665 目录(?)[-] 1非抢占式和可抢占式内核的区别 21 用户态抢占User ...

  2. Mac-配置SecureCRT

    1. Tools - Create Public Key - 2. Select Key Type 3. Create Passphrase 4.Input  Key Length 5. Genera ...

  3. golang之http

    go获取html页面 package main import ( "fmt" "io/ioutil" "net/http" "ne ...

  4. DRF最高封装的子类视图

    # 转载请留言联系 子类视图: 视图 作用 方法 父类 ListAPIView 查询多条数据 get GenericAPIView ListModelMixin CreateAPIView 新增一条数 ...

  5. selenium java读取csv文件 (数据驱动)

    javacsv2.1 下载地址:http://sourceforge.net/projects/javacsv/files/ 该链接可以下载java读取csv文件的jar 包.下载之后解压找到对应的. ...

  6. Python 进阶 之 socket模块

    Python Socket 编程详细介绍 转载地址:https://gist.github.com/kevinkindom/108ffd675cb9253f8f71?signup=true Pytho ...

  7. 使用vscode开发调试.net core应用程序并部署到Linux跨平台

    使用VS Code开发 调试.NET Core RC2应用程序,由于.NET Core 目前还处于预览版. 本文使用微软提供的示例进行开发及调试. https://github.com/aspnet/ ...

  8. 最小生成树的Kruskal算法

        库鲁斯卡尔(Kruskal)算法是一种按照连通网中边的权值递增的顺序构造最小生成树的方法.Kruskal算法的基本思想是:假设连通网G=(V,E),令最小生成树的初始状态为只有n个顶点而无边的 ...

  9. django CXRF介绍

    CSRF(Cross-site request forgery)跨站请求伪造,是攻击者利用用户的身份操作用户帐户的一种攻击方式.和XSS攻击一样,存在巨大的危害性. 一.攻击方法 1.低级的CXRF攻 ...

  10. HDU 变形课 1181【DFS/BFS】

    变形课 Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 131072/65536 K (Java/Others) Total Submissi ...