【分布式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 然后获取未拉取的离线消息然后进行存储。
相关文章:
【分布式websocket 】前端vuex管理客户端消息crud!使用localStorage来存储【第19期】
前言 聊天系统客户端是要存储消息的,因为所有所有的历史消息都从服务器拉的话一方面服务器压力大,另一方面也耗费用户流量。所以客户端存储消息是势在必行的。如何存储呢上一篇文章也写了,大概就是浏览器的话是localStorage或者IndexedDB。然…...
venv uvicorn python 虚拟服务器外网无法访问
python -m venv .venv source ./.venv/bin/activate pip install -r requirements.txt ./run.sh source ./.venv/bin/activate uvicorn main:app --reload 虚拟web服务器外网访问控制台启动命令用以下代码启动 uvicorn main:app --host 0.0.0.0 --port 8501 --reload 启动到后…...
一款博客网站源码
一款博客网站源码 源码软件库 为大家内置了主题 清爽又强大真正的永久可用的一条源码,该版本为整合版本,内置了Joe主题,搭建后直接启用即可~ 安装环境要求: PHP 7.2 以上 MySQL, PostgreSQL, SQLite 任意一种数据库支持ÿ…...
Mr-Robot1靶场练习靶场推荐小白入门练习靶场渗透靶场bp爆破wordpress
下载链接: Mr-Robot: 1 ~ VulnHub 安装: 打开vxbox,菜单栏----管理----导入虚拟电脑 选择下载完的ova文件,并修改想要保存的位置(也可以保持默认位置) 导入完成后可以根据自己的情况去配置网络链接方式 完成…...
数据仓库的设计开发应用(三)
目录 五、数据仓库的实施(一)数据仓库的创建(二)数据抽取转换加载 六、数据仓库系统的开发(一)开发任务(二)开发方法(三)系统测试 七、数据仓库系统的应用&am…...
【04】WebAPI
WebAPI 和标准库不同,WebAPI 是浏览器提供的一套 API,用于操作浏览器窗口和界面 WebAPI 中包含两个部分: BOM:Browser Object Model,浏览器模型,提供和浏览器相关的操作DOM:Document Object Model,文档模型,提供和页面相关的操作BOM BOM 提供了一系列的对象和函数,…...
数据预处理在数据挖掘中的重要性
数据挖掘作为从大量数据中提取有用信息和知识的过程,其结果的准确性和可靠性直接受到数据质量的影响。因此,数据预处理在数据挖掘中扮演着至关重要的角色。让我们探讨数据质量对数据挖掘结果的影响,并介绍常见的数据预处理方法以及它们如何提…...
Java并发编程—JUC线程池架构
Java并发编程(JUC,Java Utilities Concurrency)中的线程池架构是Java提供的一种用于管理和复用线程的机制。线程池的主要目标是减少线程创建和销毁的开销,提高系统的响应速度,并通过合理的线程管理和资源分配ÿ…...
Android input输入子系统
一.Android input输入子系统简介 Input系统是Android系统中负责处理用户输入操作的核心组件,它负责从各种输入设备(如屏幕、键盘、鼠标等)获取原始的输入事件(如按键、触摸、滑动等),并将其转换为Android应…...
如何在webapp中于动发布一个应用
目录 第一步:在webapp文件夹内自定义文件夹第二步:生成一个文本,并把后缀改为 .html第三步:进入bin文件夹打开服务第四步:打开方式选择java第六步:输入你想输出的东西第七步:双击运行即可 第一步…...
部署一个本地的ChatGPT(Ollama)
一 下载Ollama Ollama下载地址:https://ollama.com/download 下载完后 二 安装运行 双击下载好的OllamaSetup.exe开发 安装Ollama: 安装完成后,多了一个Ollama的菜单如下图 : Ollama安装好默认是配置开机运行,如果没有运行可以在…...
Vue 3中的reactive:响应式状态的全面管理
🤍 前端开发工程师、技术日更博主、已过CET6 🍨 阿珊和她的猫_CSDN博客专家、23年度博客之星前端领域TOP1 🕠 牛客高级专题作者、打造专栏《前端面试必备》 、《2024面试高频手撕题》 🍚 蓝桥云课签约作者、上架课程《Vue.js 和 E…...
【网络】详解HTTPS及探究加密过程
目录 一、什么是HTTPS1、加密解密是什么2、为什么要加密3、常见的加密方式1、对称加密2、非对称加密 二、探究HTTPS如何实现加密1、方案一----只使用对称加密2、方案二----只使用非对称加密3、方案三----双方都使用非对称加密4、方案四----非对称加密 对称加密5、中间人攻击6、…...
【C语言】字符与字符串---从入门到入土级详解
🦄个人主页:修修修也 🎏所属专栏:C语言 ⚙️操作环境:Visual Studio 2022 目录 一.字符类型和字符数组(串)简介 1.ASCII 2.定义,初始化,使用 1>字符的定义及初始化 2>字符串的定义及初始化 二.…...
Github Copilot 工具,无需账号,一键激活
① 无需账号,100%认证成功!0风险,可联网可更新,,支持copilot版本升级,支持chat ② 支持windows、mac、linux系统等设备 ③一号通用,支持所有IDE(AppCode,CLion,DataGrip,GoLand,IntelliJ IDEA …...
node: -max-old-space-size=xxx is not allowed in NODE_OPTIONS
问题描述 在启动node项目时,出现了OOM参照网上的处理方案,设置了环境变量: export NODE_OPTIONS"–max-old-space-size8192"当再次通过npm run docs:dev运行node项目的时候出现了如下错误: node: -max-old-space-siz…...
k8s编排系统
Kubernetes(简称K8s)是一个开源的容器编排系统,由Google基于其内部的Borg项目开发,并于2014年正式对外发布。目前,Kubernetes已成为云原生计算基金会(Cloud Native Computing Foundation, CNCF)…...
samba服务器的配置
需求:在Linux上搭建一个文件共享服务,创建不同的账号给予不同的权限,在windows可以直接访问该共享目录 介绍 Samba 是一个强大的工具,使得不同操作系统之间可以无缝地共享文件和资源,促进了跨平台环境下的协作和通信…...
H12-821_279
279.第三类LSA的Link ID是: A.所描述的ABR的Router ID B.所在网段上DR的端口IP地址 C.所描述的目的网段 D.生成这条LSA的路由器的Router ID 答案:C 注释: OSPF的LSA可以单独描述网络信息、拓扑信息,也可以同时描述网络信息和拓扑信息。 LSA3…...
Stable Diffusion科普文章【附升级gpt4.0秘笈】
随着人工智能技术的飞速发展,我们越来越多地看到计算机生成的艺术作品出现在我们的生活中。其中,Stable Diffusion作为一种创新的图像生成技术,正在引领一场艺术创作的革命。本文将为您科普Stable Diffusion的相关知识,带您走进这…...
synchronized 学习
学习源: https://www.bilibili.com/video/BV1aJ411V763?spm_id_from333.788.videopod.episodes&vd_source32e1c41a9370911ab06d12fbc36c4ebc 1.应用场景 不超卖,也要考虑性能问题(场景) 2.常见面试问题: sync出…...
[Java恶补day16] 238.除自身以外数组的乘积
给你一个整数数组 nums,返回 数组 answer ,其中 answer[i] 等于 nums 中除 nums[i] 之外其余各元素的乘积 。 题目数据 保证 数组 nums之中任意元素的全部前缀元素和后缀的乘积都在 32 位 整数范围内。 请 不要使用除法,且在 O(n) 时间复杂度…...
什么?连接服务器也能可视化显示界面?:基于X11 Forwarding + CentOS + MobaXterm实战指南
文章目录 什么是X11?环境准备实战步骤1️⃣ 服务器端配置(CentOS)2️⃣ 客户端配置(MobaXterm)3️⃣ 验证X11 Forwarding4️⃣ 运行自定义GUI程序(Python示例)5️⃣ 成功效果 数学表达式:dst(x,y) erode(src(x,y)) min(x,y)src(xx,yy) 腐蚀也是图像形态学的基本功能之一,腐蚀跟膨胀属于反向操作,膨胀是把图像图像变大,而腐蚀就是把图像变小。腐蚀后的图像变小变暗淡。 腐蚀…...
HDFS分布式存储 zookeeper
hadoop介绍 狭义上hadoop是指apache的一款开源软件 用java语言实现开源框架,允许使用简单的变成模型跨计算机对大型集群进行分布式处理(1.海量的数据存储 2.海量数据的计算)Hadoop核心组件 hdfs(分布式文件存储系统)&a…...
虚拟电厂发展三大趋势:市场化、技术主导、车网互联
市场化:从政策驱动到多元盈利 政策全面赋能 2025年4月,国家发改委、能源局发布《关于加快推进虚拟电厂发展的指导意见》,首次明确虚拟电厂为“独立市场主体”,提出硬性目标:2027年全国调节能力≥2000万千瓦࿰…...
【MATLAB代码】基于最大相关熵准则(MCC)的三维鲁棒卡尔曼滤波算法(MCC-KF),附源代码|订阅专栏后可直接查看
文章所述的代码实现了基于最大相关熵准则(MCC)的三维鲁棒卡尔曼滤波算法(MCC-KF),针对传感器观测数据中存在的脉冲型异常噪声问题,通过非线性加权机制提升滤波器的抗干扰能力。代码通过对比传统KF与MCC-KF在含异常值场景下的表现,验证了后者在状态估计鲁棒性方面的显著优…...
【Android】Android 开发 ADB 常用指令
查看当前连接的设备 adb devices 连接设备 adb connect 设备IP 断开已连接的设备 adb disconnect 设备IP 安装应用 adb install 安装包的路径 卸载应用 adb uninstall 应用包名 查看已安装的应用包名 adb shell pm list packages 查看已安装的第三方应用包名 adb shell pm list…...
破解路内监管盲区:免布线低位视频桩重塑停车管理新标准
城市路内停车管理常因行道树遮挡、高位设备盲区等问题,导致车牌识别率低、逃费率高,传统模式在复杂路段束手无策。免布线低位视频桩凭借超低视角部署与智能算法,正成为破局关键。该设备安装于车位侧方0.5-0.7米高度,直接规避树枝遮…...
