[qiankun]-多页签缓存

news2024/11/28 8:33:26

[qiankun]-多页签缓存

  • 环境
  • 功能需求
  • 多页签缓存方案
    • 方案1.主服务进行html替换
    • 方案2.微服务vnode 替换
    • 方案3.每个微服务都不卸载
      • 微服务加载方式的选择
      • 微服务的路由路径选择
      • 微服务的缓存工具
      • 微服务的容器
        • 使用tab作为微服务的挂载容器
        • 使用微服务路由作为微服务的挂载容器
          • 场景描述
      • 微服务的缓存
        • 缓存微服务
        • 删除微服务
        • 不同路由同一微服务情况

管理系统比较常用的一个功能就时多页签的缓存,我们通过缓存已经打开的页签,并在切换页签的时候看到之前的查询结果,在关闭页签的重新点击菜单那时,看到的是新的没有查询记录界面

环境

语言:采用的主流的vue3.x+ts开发
UI框架:使用的是ant-design框架
其它工具:使用了微服务技术-qiankun
缓存工具:keep-alive

功能需求

  • 通过点击菜单,打开一个菜单页签(点击后展示的菜单称之为页签):

    如果点击菜单之前已打开页签中没有该菜单,则该页面应该是初始页面状态;

    如果点击菜单之前已打开页签中有该菜单,则该页面应该是上次操作后状态;

  • 切换已打开的页签:

    则页面应该都是上次操作后状态;

  • 关闭页签后再次点击菜单:

    因为点击菜单之前关闭页签,所以已打开页签中没有该菜单,则该页面应该是初始页面状态;

多页签缓存方案

方案1.主服务进行html替换

通过存储每个微服务容器的html内容,然后在切回当前页签的时候,微服务容器使用缓存的html替换,也就是所谓的替换innerHTML。

方案尝试结果描述:
替换的内容,使得切换回原有页面确实是上次的查询结果页面,但是页面失去了响应性,变成了静态的HTML页面,包括下拉框都没有了

方案2.微服务vnode 替换

通过存储每个微服务容器的 vnode 内容,然后在切回当前页签的时候,创建微服务实例的时候,使用vnode替换掉原有的render渲染函数

方案尝试结果描述:
因为本人使用的vue3开发,使用render渲染函数是vue2创建vue实例的方法,因此该方案无法实现使用vnode替换掉原有的render渲染函数

尝试了vnode的缓存强制替换的可能性,vue3提示_vnode是只读属性不可以设置

方案3.每个微服务都不卸载

以上两个方案,都是基于同时只加载一个微服务,并且在切换的时候卸载当前微服务,之所以先尝试前两个方案也是因为,如果页面每个微服务都不卸载,当打开的页签过多时会有性能问题,因为微服务总数量暂时有限,该问题此时先不考虑了,如果之后有需要会另外总结

因为前两个方案都不可行,只能尝试该方案,方案描述:

微服务加载方式的选择

qiankun加载加载微服务的方式有两种:

  1. 是注册加载,通过劫持路由,会根据路由变化加载每个微服务
    registerMicroApps,是根据路由的变化加载微服务的,只要路由变化,就会触发微服务重新加载微服务,因此无法阻止微服务的重新加载,缓存不能被使用,指定容器的内容会被覆盖,因此感觉不适合缓存页签的方案
  2. 是手动加载,可以自己决定什么时候加载
    loadMicroApp ,是手动加载,因此能决定是重新加载,还是使用缓存,感觉适合使用该方式

因此选择手动加载微服务的方式

微服务的路由路径选择

主服务具有公共页面,例如404,intro等路由页面,公共页面与微服务都是展示在页面的主体区,并且不需要缓存,因为没有操作功能,当然缓存也是可以的。微服务展示的时候,公共路由页面不可展示,路由也需要变为微服务的路由,不能使用之前的路由路径。

因此可以使用router.push(),或者router.replace()改变浏览器的路由路径,有说可以把路由router想象成一个访问记录的栈,router.replace() 是替换掉栈顶,而router.push() 则是向栈中再堆入一个新记录

考虑过所有微服务使用同一个路由路径,但是因为浏览器的前进后退记录管理服务,因此每个微服务的路由路径不能完全相同,否则无法区分微服务的前进后退记录,所以也不能使用replace方法了

因此每个微服务页面具有一个唯一的路由路径,需要使用router.push记录所有的路由路径,并且需要用来加载微服务的路由组件(如果没有找到指定的路由,系统会跳转404,因此需要微服务的路由组件,微服务众多,因此所有微服务可以采用相同的前缀,用以匹配到同一个路由组件),一个微服务路由组件就能够满足需求

相同的前缀,/micro/XXXX/XXXX,例如:/micro/service/function

{
    path: "/micro/:pathMatch(.*)*",///micro/:projectName/:page
    meta: { auth: true },
    component: () => import(/* webpackChunkName: "micro" */ "../micro/index.vue")
  }

微服务的缓存工具

默认情况下,一个组件实例在被替换掉后会被销毁。这会导致它丢失其中所有已变化的状态 —— 当这个组件再一次被显示时,会创建一个只带有初始状态的新实例。

keep-alive 是 vue 内置的动态组件缓存工具

keep-alive 缓存路由的key默认是每个路由的name,一般的路由缓存因为每个路由设置了不同的name,所以include包含需要缓存的路由的name即可

那么针对想更改缓存Key的情况:

<router-view v-slot="{ Component, route }">
  <keep-alive :include="cachePannels">
    <component :is="wrap(route, Component)" :key="wrapKey(route.path)" />
  </keep-alive>
</router-view>

以下对component与key的处理,PROJECT.cacheKey设置缓存的key字段:

const wrap = (route, component) => {
  component.type.name = "path" == PROJECT.cacheKey ? route.path : store.state.pathMap[route.path].id;
  return component
};
const wrapKey = (path) => {
  if ("path" == PROJECT.cacheKey) {
    return path
  } else {
    return store.state.pathMap[path].id
  }
}

经过测试发现若缓存的字段是path,则缓存成功,若是key是改成id则缓存不成功,因为对于源码的理解并不深入,所以目前并不理解原因,也暂时不做深入,这里还是想吐槽一句,看到在源码处这个问题已经被提出几年了,但是都没有一个官方正式的回应,都是小伙伴提供的各种解决方案,而且就像上面说的绑定的key还必须是path其它不可以。。。

好吧,暂时不纠结了,既然path可用,就确定使用path,以下是最终代码

<router-view v-slot="{ Component, route }">
  <keep-alive :include="cachePannels">
    <component :is="wrap(route, Component)" :key="route.path" />
  </keep-alive>
</router-view>
const wrap = (route, component) => {
  component.type.name = route.path;
  return component
};

因为微服务使用的是同一个路由组件,因此name相同,那么正好需要使用根据key进行缓存的功能

基于上述原因,使用keep-alive缓存,路由path,作为缓存的key。

关于keep-alive重写的功能以后有机会在尝试吧

微服务的容器

一开始我是倾向于直接用微服务路由组件作为加载微服务的容器

但是使用路由的path作为路由缓存的key,理论讲一旦path发生变更,则路由组件会被销毁重新加载,但是微服务切换时到底组件是否会被销毁?在尝试时存在一些无可避免的问题,当时没有成功

使用tab作为微服务的挂载容器

这里先讲述一个成功缓存的方式

<template>
<a-tabs  v-model:activeKey="activeKey"
  @tabClick="clickTab"  @edit="closeTab">
  <a-tab-pane v-for="item in cacheList" :key="item.id" :tab="item.title">
    <div :id="'micro'+item.id" class="micro-tab"></div>
  </a-tab-pane>
</a-tab>

<router-view v-slot="{ Component, route }">
  <keep-alive :include="cachePannels">
    <component :is="wrap(route, Component)" :key="route.path" />
  </keep-alive>
</router-view>
</template>

微服务路由 micro.vue

<template>
</template>
<script lang="ts" setup>
import { useStore } from "store";
const store = useStore();
store.commit("loadMicroApp");
</script>

注意,虽然微服务加载是在tab中挂载的,但是router-view此时是要正常加载微服务路由的,因为路径要有对应的匹配路由,但是微服务又不在其中挂载,所以隐藏微服务路由 micro.vue 的展示即可

使用微服务路由作为微服务的挂载容器

加载的时候,因为使用的path作为key,理论来讲,keep-alive应该将每个微服务作为一个单独的路由进行缓存.

但是实际情况有所不同,现象描述:

在打开页签的过程中,每次都是onMount了的,切换的时候,可以看到确实缓存了微服务,每次切换的时候显示的是缓存页面

但是在关闭页签的时候出现了问题,一旦关闭了其中一个正在展示的微服务,其它微服务页面就白屏了,就像是其它路由组件都被删除了?!所以为什么作为单独路由缓存的其它页面没有正常展示?但是如果关闭的是没有展示的页签,则并不影响当前路由的展示与后续的切换

因为该问题没有解决,所以最终没有采用该方式!!下面采用路由组件作为容器时的现象

场景描述

主服务首次点击菜单A,打开页签A,挂载A服务 onMounted onActivated

主服务首次点击菜单B,打开页签B,挂载B服务 onMounted onActivated

切换A服务,B onDeactivated,A onActivated

切换B服务,A onDeactivated,B onActivated

此时关闭B服务:

实际:B onUnmounted,A onMounted onActivated

理论:B onUnmounted,A onActivated

这就像是A挂载到了B的路由组件上了?
正常的切换时keep-alive缓存的组件

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-61K3ycOm-1677045679175)(2023-01-03-11-37-19.png)]

vue 的组件,不同路径,同一个路由, 缓存的组件为同一个

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-7wZSirDR-1677045679177)(2023-01-03-15-16-52.png)]

在这里插入图片描述

因此同组件路由卸载的时候,另外的就无法展示了,原因找到了,但是如何区分开?尝试过使用cloneVnode 克隆micro.vue组件,但是无效,所以暂时未找到解决方案

微服务的缓存

缓存微服务

需要缓存的微服务正常手动加载微服务即可,并缓存该微服务

最早的时候是直接缓存的

cacheMap[microApp.path] = loadMicroApp(microApp)

后来在实践中发现直接缓存是存在问题的,例如当loadMicroApp失败的时候(微服务不存在,不可用的情况),此时缓存的微服务实例是不存在的,自然对于该微服务实例后续的卸载会导致报错

因此,当缓存微服务的时候需要确保微服务加载成功:

const appMicro = loadMicroApp(microApp, { singular: false }, microLifeCycle);
appMicro.mountPromise.then((res) => {
  //微服务加载成功时保存微服务
  state.micro.cacheMap[microApp.path] = appMicro;
}).catch((error) => {
  //微服务加载失败时提示错误
  console.error(`mountPromise error`, error)
})

microLifeCycle是微服务的生命周期,可以在其中设置微服务的加载动画

删除微服务

关闭页签,也就是删除缓存微服务时,注意一定要先卸载微服务,unmount,否则下次加载该微服务时会报已挂载错误

//卸载微服务
cacheMap[microApp.path].unmount();
//删除微服务实例
delete cacheMap[microApp.path]

不同路由同一微服务情况

如果微服务有两个路由,而两个路由页面都点击后要缓存,此时也是正常加载即可,当作两个不同微服务加载即可,也不会报已挂载错误,因为路径不同可以当作缓存的是两个微服务(不同于在micro.vue中挂载,该路由组件中如果当作两个微服务挂载是会报已挂载错误的),因为是加载在tab中,彼此并不互相影响

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

day18_集合_List

今日内容 上课同步视频:CuteN饕餮的个人空间_哔哩哔哩_bilibili 同步笔记沐沐霸的博客_CSDN博客-Java2301 零、 复习昨日 一、集合框架体系 二、Collection 三、泛型 四、迭代 五、List 六、ArrayList 七、LinkedList 零、 复习昨日 throw和throws什么区别 throwthrows位置方法…

Word中批量调整图片大小

当一个文档中图片较多&#xff0c;又需要调整图片大小时&#xff0c;这时可以通过“宏”执行代码来批量调整。打开一个Word文档。“AltF8"键打开宏。设置“宏名”&#xff0c;并单击“创建”。创建完宏后&#xff0c;将进入Visual Basic 编辑器界面。在代码编辑区全选&…

WebDAV之π-Disk派盘+文件管理器

文件管理器 支持WebDAV方式连接π-Disk派盘。 推荐一款iOS上的免费文件管理器新秀。 文件管理器这是一款功能强大的文件管理工具,支持zip,rar,7z等压缩包的解压和压缩,支持小说,漫画,视频下载及播,极大提升日常办公,娱乐,文件管理的工作效率,使得文档的归档和管理随心…

Android system实战 — Android R(11) 进程保活白名单

Android system实战 — Android R 进程保活白名单0. 前言1. 具体实现1.1 准备工作1.2 源码实现1.2.1 源码1.2.2 diff文件0. 前言 最近在Android R上实现一些需求&#xff0c;进行记录一下&#xff0c;关于进程保活的基础知识可以参考Android system — 进程生命周期与ADJ&#…

纯手动搭建hadoop3.x集群记录002_安装hadoop3.x_创建xsync分发工具_配置ssh免密登录---大数据之Hadoop3.x工作笔记0164

1.首先我有 172.19.126.117 母机 对应 172.19.126.122 虚拟机 172.19.126.116 母机 对应 172.19.126.121 虚拟机 172.19.126.115 母机 对应 172.19.126.120 虚拟机 对吧,然后我们从115上 开始安装hadoop 2. 然后走到这个opt/software文件夹中,然后解压 hadoop-3.1.3.tar.…

nn.Dropout随机丢神经元的用法

前言&#xff1a; pytorch与tensorflow中均有nn.dropout,两者之间的使用方法&#xff0c;下面将介绍。 一、torch.nn.dropout 说明文档&#xff1a; r"""During training, randomly zeroes some of the elements of the input tensor with probability :att…

人员行为识别系统 TensorFlow

人员行为识别系统人员行为识别系统通过TensorFlow深度学习技术&#xff0c;人员行为识别算法对画面中区域人员不按要求穿戴、违规抽烟打电话、睡岗离岗以及作业流程不规范实时分析预警&#xff0c;发现违规行为立即抓拍告警。深度学习应用到实际问题中&#xff0c;一个非常棘手…

2.22 位运算

位运算 预备知识 首先注意二进制位数从0开始记录&#xff0c;即 15&#xff08;1111&#xff09;&#xff0c;位数分别为3210 左移和右移 左移 << 将某个数的二进制向左移动几位&#xff0c;低位补0 如5>>2 即20&#xff0c;左移k位即相当于乘上2的k次方 右移 >…

C++学习笔记-数组

所谓数组&#xff0c;就是相同数据类型的元素按一定顺序排列的集合&#xff0c;就是把有限个类型相同的变量用一个名字命名&#xff0c;然后用编号区分他们的变量的集合&#xff0c;这个名字称为数组名&#xff0c;编号称为下标。组成数组的各个变量称为数组的分量&#xff0c;…

[面向小白]一篇博客带你认识什么是栈以及如何手撕一个栈

目录 0.前言 1.什么是栈 2.实现栈所选择的基本结构 3.认识栈的小练习 4. 用代码实现一个栈 4.1 用什么可以描述出一个栈 4.2栈接口的设计原则 4.3栈的初始化 4.4栈的插入 4.5 栈的删除 4.6 栈的判空 4.7栈的有效元素的数量 4.8取出栈顶元素 4.9栈的销毁 5. 对实…

BUUCTF-[ACTF新生赛2020]Splendid_MineCraft

题目下载&#xff1a;下载 这道题涉及SMC&#xff0c;动静态调试。 查壳&#xff0c;无壳32位&#xff0c;载入IDA 进入主函数main&#xff1a; 从上面可以看出&#xff0c;flag长度为26&#xff0c;前五个是ACTF{&#xff0c;最后一位是}。 strtok()函数用法&#xff1a;st…

sso单点登录

文章目录 目录 文章目录 前言 一、sso结构实现 二、使用步骤 2.1 建一个spring cloud 项目 2.2 common下的core的配置 2.3 实现系统的业务微服务 2.4 sso模块的编写 总结 前言 单点登录(SingleSignOn&#xff0c;SSO)&#xff0c;就是通过用户的一次性鉴别登录。当用户在身份…

复习知识点三:做人不能半途而废,就算躺平也要躺最舒服的那张床

目录 运算符​编辑 键盘录入: 练习:键盘输入数字并求和 练习: 算术运算符 隐式转换(自动类型提升) 强制转换 练习1: 字符串的 "" 操作 ​编辑 练习 1: 练习2: 练习3: 自增自减运算符 赋值运算符 关系运算符(比较运算符)的分类 练习: 逻辑运算符 短路逻辑运…

电商平台销量查询:2023年1月牛奶乳品热门排行榜

随着人们消费能力的提升以及健康意识的增强&#xff0c;牛奶乳品已经成为居民日常饮食中的重要组成部分&#xff0c;伴随人们整体消费的增长&#xff0c;牛奶乳品行业也越来越成熟。 今年1月份我国牛奶乳品行业的整体趋势如何呢&#xff1f;结合数据我们一同来分析&#xff01;…

国外博士后待遇情况汇总

许多老师再考虑申请国外博士后的时候会顾虑待遇方面的问题&#xff0c;对此知识人网小编整理关于主要国家博士后待遇情况的汇总。美国&#xff1a;美国机会更多&#xff0c;生活质量更高&#xff0c;生活空间也广。美国的年薪一般是3.0-6.5万美金左右&#xff0c;刚博士毕业出来…

无脑霸总漫开播,她穿书变成恶毒女配,本想和霸总离婚摆烂

无脑霸总漫开播&#xff0c;她穿书变成恶毒女配&#xff01;本想和霸总离婚摆烂&#xff0c;不料却被霸总盯上了&#xff5e;虐妻一时爽&#xff0c;追妻火葬场&#xff0c;曾经的我你爱搭不理&#xff0c;现在的我你高攀不起&#xff01;#无脑霸总漫开播 #如何在无脑霸总漫里艰…

Sql Server数据库实现表中字段的列加密研究

1、问题描述 去年6月份的时候做过一个薪酬系统&#xff0c;要对里面的一些敏感字段进行一下加密。Sqlserver列加密可以参考官方文档&#xff1a;SQL Server 技术文档 - SQL Server | Microsoft Learn。主要看下来有三种加密方法&#xff1a;1、利用证书对数据进行加密和解密。2…

Google Guice 3:Bindings(1)

1. 序言 上一篇博客&#xff0c;《Google Guice 2&#xff1a;Mental Model》&#xff0c;讲述了Guice的建模思路&#xff1a;Guice is a map Guice官网认为&#xff1a;binding是一个对象&#xff0c;它对应Guice map中的一个entry&#xff0c;通过创建binding就可以向Guice …

RocketMQTemplate 实现消息发送

代码托管于gitee&#xff1a;easy-rocketmq 文章目录一、前置工作二、消费者三、生产者1. 普通消息2. 过滤消息3. 同步消息4. 延时消息5. 批量消息6. 异步消息7. 单向消息8. 顺序消息9. 事务消息概要Demo源码解读一、前置工作 1、导入依赖 <dependency><groupId>…

《羊驼亡命跑》 NFT 系列:羊驼跑酷套装来袭!

完美的羊驼跑酷&#xff01;这一系列植物、平台、愤怒的农民和神秘物品与你们的 Alpacadabraz 化身都是绝配。 关于 Paca Death Run Alpacadabraz 团队推出的首个主要体验的一切都很吸引&#xff01;这款跑酷游戏垂直填满了一个整个 1x1 The Sandbox LAND&#xff0c;挑战玩家在…