【分布式websocket 】前端vuex管理客户端消息crud!使用localStorage来存储【第19期】

前言

聊天系统客户端是要存储消息的,因为所有所有的历史消息都从服务器拉的话一方面服务器压力大,另一方面也耗费用户流量。所以客户端存储消息是势在必行的。如何存储呢上一篇文章也写了,大概就是浏览器的话是localStorage或者IndexedDB。然后手机端和桌面端就是sqllite了。这样子消息的存储结构以及消息的增删改查也是需要一套的了。本篇文章将着重从自己的开源项目技术选型来进行分享。vuex进行增删改查。B站会录制视频同步分享。

目前已经写的文章有。并且有对应视频版本。
git项目地址 【IM即时通信系统(企聊聊)】点击可跳转
sprinboot单体项目升级成springcloud项目 【第一期】
前端项目技术选型以及页面展示【第二期】
分布式权限 shiro + jwt + redis【第三期】
给为服务添加运维模块 统一管理【第四期】
微服务数据库模块【第五期】
netty与mq在项目中的使用(第六期(废弃))】
分布式websocket即时通信(IM)系统构建指南【第七期】
分布式websocket即时通信(IM)系统保证消息可靠性【第八期】
分布式websocket IM聊天系统相关问题问答【第九期】
什么?websocket也有权限!这个应该怎么做?【第十期】
分布式ID是什么,以美团Leaf为例改造融入自己项目【第十一期】
IM聊天系统为什么需要做消息幂等?如何使用Redis以及Lua脚本做消息幂等【第12期】
微信发送一条消息经历哪些过程。企业微信以及钉钉的IM架构对比【第13期】
微信群为什么上限是500人,IM设计系统中的群聊的设计难点【第14期】
【分布式websocket】RocketMQ发送消息保证消息最终一致性需要做哪些处理?【第15期】

【分布式websocket】群聊中的各种难点以及解决推拉结合【第16期】

【分布式webscoket】未读消息如何设计?解决缓存与数据库数据一致性!推送未读消息流程【第17期】

IM系统客户端消息存储在手机电脑浏览器分别存储在什么地方?对消息加密策略?如何保证服务端消息和客户端消息一致性【第18期】
【分布式websocket】聊天系统消息加密如何做【第20期】
【分布式webscoket】IM聊天系统消息如何存储 如何分库分表以及Seata解决事务以及ShardingSphere-Scaling解决数据迁移【第21期】

客户端消息结构:

技术选型在浏览器端的localStorage,当然是有缺陷的。后续根据情况再进行优化。页面如下。
在这里插入图片描述

在这里插入图片描述

chats: []            数组 存放每一个聊天用户lastContent:	 存放最后一条消息用于显示tagrgetId: 		 标识唯一会话,可以考虑改成会话id,目前使用的是单聊是对方的id,群聊是群聊idtype :			 标记是私聊还是群聊unreadCount:	 未读消息数量 (TODO)messgaes :[]    存放每一个用户下面具体的聊天消息,数组type:		 用于标记消息是自己发的还是别人的,用于前端显示样式group:        用于区分消息是群聊还是单聊 ,创建消息的时候会使用到msgid:        消息唯一idavatarUrl:    用于页面上面显示聊天头像框content:	     消息内容tagrgetId:     标识唯一会话id
privateMsgMaxId: 拉取消息id

如下
客户端消息操作主要是 .

  • 添加 1.上线后拉取未读消息要存储未读消息 2.发送消息需要添加消息3.收到消息需要添加
  • 查询 进入聊天页面需要可以查到消息
  • 修改 消息发送失败需要修改状态发送失败
  • 删除 前端存储有限制只能维护一定时间的历史消息。更多的历史消息查询客户端

vuex基本概念概述

export default createStore({state,mutations,actions,getters,modules: {}
})

大概就是这么几个部分。
总结来说,Getter 用于获取由 state 计算得出的数据;
Mutation 用于同步地改变 state,
Action 则封装了异步操作,并最终通过 commit 来间接触发 mutations 更新状态。
state 就是封装变量的地方。

Vuex 允许将应用程序的状态集中存储在一个共享的 store 中,避免了组件之间通过 props 和 events 进行状态传递的复杂性和繁琐性。这使得状态管理更加清晰和易于维护。通过 Vuex 管理状态,整个应用程序共享同一个状态树,确保了状态的一致性和同步性。

场景介绍

消息查询
// 创建一个计算属性,该属性基于其他响应式状态计算值const computedChats = computed(() => {let chat = null;console.log("computedChats route.query.groupId", route.query.groupId);if (state.current == 1) {chat = {targetId: state.toUser.openid,};} else {chat = {// targetId: state.toUser.openid,targetId: state.groupId,};}const idx = store.getters.findChatIdx(chat);if (idx == null || idx == undefined) {return [];}if (store.state.chats[idx] == null ||store.state.chats[idx] == undefined) {return [];}console.log("computedChats idx", idx);console.log("computedChats 寻找成功啦", store.state.chats[idx]);return store.state.chats[idx];});

封装了一个计算属性。用于监听state里面的消息变化。逻辑大概是拿到当前会话的id,单聊的话就是对话的openid。然后去store里面去找一下。找不到的返回空数组。找到的话返回当前聊天下的所有信息.

对应前台页面

渲染一下这个compute属性

   <list-scroll :scroll-data="computedChats.messages"><div class="swiper-container"><divclass="content"v-for="(item, index) in computedChats.messages":key="index"><div class="d-felx justify-start " v-if="item.type === 'self'"><div style="display: flex;"><van-imagewidth="35px"height="35px"fit="cover":src="userInfo.avatarUrl"/><div class="font-18 content1"><text>{{ item.content }}</text></div></div></div><divstyle="display: flex; justify-content: flex-end;"v-if="item.type === 'receive'"><div class="font-18 content2"><text>{{ item.content }}</text></div><div class=""><van-imagewidth="35px"height="35px"fit="cover":src="toUser.avatarUrl"/></div></div></div></div></list-scroll>

消息添加

分为离线数据添加 和在线数据添加。
离线数据添加需要使用到action,异步的去后台拉取然后插入。
在线数据直接调用mutation数据插入。

 /*** 插入消息.* @param {*} state* @param {*} msgInfo 当前消息*/insertMessage(state, msgInfo) {console.log("insertMessage",msgInfo)state.privateMsgMaxId = msgInfo.msgId;state.groupMsgMaxId = msgInfo.msgId;// 如果是已存在消息,则覆盖旧的消息数据let chat = this.getters.findChat(msgInfo);if (chat == null) {this.commit("createChat", msgInfo);chat = this.getters.findChat(msgInfo);}if(chat == null){console.log("没有找到chat",chat);return;}chat.messages.push(msgInfo);this.commit("saveToStorage");},

第一步,先更新一下这个最大的消息id。然后去store里面去找当前消息。找到之后给当前chat里面推送消息。并且同步的保存到Storgae里面.

/***  state.chats 将更新后的存储.* @param {*} state*/saveToStorage(state) {let userId = state.userInfo.openid;let key = "chats-" + userId;let chatsData = {privateMsgMaxId: state.privateMsgMaxId,groupMsgMaxId: state.groupMsgMaxId,chats: state.chats,};localStorage.setItem(key, JSON.stringify(chatsData));},

这个存储的逻辑就是简单的将消息序列化后放到localStorage里面。

强调一下这个离线消息拉取的步骤;需要后台sql的配合。
 async pullOffline(ctx) {// 获取当前store中的privateMsgMaxIdconst privateMsgMaxId = ctx.state.privateMsgMaxId+"";console.log("privateMsgMaxId",ctx.state.privateMsgMaxId)const res = await getChatContentAll(privateMsgMaxId);const contentAll = res.contentfor (var i = 0; i < contentAll.length; i++) { ctx.commit("initInsertMessage", contentAll[i]); }}

调用后台接口getChatContentAll 然后获取未拉取的离线消息然后进行存储。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/544280.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

使用Lua编写Wireshark解析ProtoBuf插件

文章目录 Wireshark Protobuf Lua-dissectorStep 1: 获取 WiresharkStep 2: 配置ProtoBuf相关设置添加ProtoBuf查找路径 Step 3 运行和调试Lua代码1. 添加Lua脚本2. 运行和调试 Step 4: 写Lua Dissector代码 :)Step 5(Optional): Decode AsGithub工程地址 Wireshark Protobuf L…

THM学习笔记—RootMe

nmap扫描&#xff0c;发现22端口和80端口打开 dirsearch扫描&#xff0c;注意到/panel和/uploads&#xff0c;在浏览器中打开 可以上传文件&#xff0c;尝试反弹shell 在尝试过程中发现网站不能上传.php文件&#xff0c;只需要将后缀更改为.php5之类即可 成功 查找文件&#x…

Tomcat Session 集群 ---------会话保持

一、 负载均衡、反向代理 环境搭建&#xff1a; nginx服务器192.168.246.7 tomcat 1服务器192.168.246.8 tomcat 2服务器192.168.246.9 7-1 nginx服务器搭建 [rootzzcentos1 ~]#systemctl stop firewalld [rootzzcentos1 ~]#setenforce 0 [rootzzcentos1 ~]#yum install …

【网络】详解HTTPS及探究加密过程

目录 一、什么是HTTPS1、加密解密是什么2、为什么要加密3、常见的加密方式1、对称加密2、非对称加密 二、探究HTTPS如何实现加密1、方案一----只使用对称加密2、方案二----只使用非对称加密3、方案三----双方都使用非对称加密4、方案四----非对称加密 对称加密5、中间人攻击6、…

【Java】List, Set, Queue, Map 区别?

目录 List, Set, Queue, Map 区别&#xff1f; Collection和Collections List ArrayList 和 Array区别&#xff1f; ArrayList与LinkedList区别? ArrayList 能添加null吗&#xff1f; ArrayList 插入和删除时间复杂度&#xff1f; LinkedList 插入和删除时间复杂度&…

部署一个本地的ChatGPT(Ollama)

一 下载Ollama Ollama下载地址&#xff1a;https://ollama.com/download 下载完后 二 安装运行 双击下载好的OllamaSetup.exe开发 安装Ollama: 安装完成后&#xff0c;多了一个Ollama的菜单如下图 &#xff1a; Ollama安装好默认是配置开机运行&#xff0c;如果没有运行可以在…

OpenCV 图像重映射函数remap()实例详解

OpenCV 图像重映射函数remap()对图像应用通用几何变换。其原型如下&#xff1a; void remap(InputArray src, OutputArray dst, InputArray map1, InputArray map2, int interpolation&#xff0c; int borderMode BORDER_CONSTANT&#xff0c; const Scalar & borde…

Jenkins 面试题及答案整理,最新面试题

Jenkins中如何实现持续集成与持续部署&#xff1f; Jenkins通过自动化构建、测试和部署应用程序来实现持续集成与持续部署&#xff08;CI/CD&#xff09;。这个过程包括以下步骤&#xff1a; 1、源代码管理&#xff1a; Jenkins支持与多种版本控制系统集成&#xff0c;如Git、…

基于FPGA的光纤通信系统设计

文章目录 光纤通信系统的组成发送端FPGA端口定义状态机设计代码示例 接收端功能模块端口定义状态机设计 光纤通信系统的组成 发送端FPGA 发送控制逻辑、数据编码、校验码生成、缓存控制、时钟控制 端口定义 状态机设计 代码示例 接收端功能模块 接收端控制逻辑、数据解码、…

CentOS部署 JavaWeb 实现 MySql业务

一、项目打war包 在eclispe或idea中找到项目&#xff0c;右键打war包。 二、上传项目到linux 2.1云服务器虚拟机均可 以tomcat为例 /usr/local/tomcat/webapps 将war包通过ssh连接上传到webapps目录下。 如果是root目录则不需要项目名即 ip或域名端口直接访问&#xff08…

第二门课:改善深层神经网络<超参数调试、正则化及优化>-超参数调试、Batch正则化和程序框架

文章目录 1 调试处理2 为超参数选择合适的范围3 超参数调试的实践4 归一化网络的激活函数5 将Batch Norm拟合进神经网络6 Batch Norm为什么会奏效&#xff1f;7 测试时的Batch Norm8 SoftMax回归9 训练一个SoftMax分类器10 深度学习框架11 TensorFlow 1 调试处理 需要调试的参…

ClickHouse:一款高效且强大的列式数据库管理系统

ClickHouse是一款开源的列式数据库管理系统&#xff0c;专为大规模数据仓库和数据分析应用而设计。它允许用户快速地存储和处理海量数据&#xff0c;同时提供了简单易用的SQL接口。本文将介绍ClickHouse的概念、技术原理以及使用案例&#xff0c;并探讨其优势和挑战。 一、引言…