微前端(qiankun)多页签方案动态路由缓存问题

前言:

因为前期一直在做低码平台,里面有编辑页面跟预览页面,最近新加的需求是,这俩页面是动态路由,需要做缓存处理,并且集成到微前端主应用。

注意:阅读此文章前,需要对keep-alive原理跟微前端有一定的了解哦!

keep-alive源码解析

js 复制代码
<keep-alive :include="cachedViews">
  <router-view :key="key" />
</keep-alive> 

include数组,数组里面包裹的是组件name,(它是一个抽象组件,打开vue调试工具你没法看到这个组件的显示。建议集成组件做个扩展,将它改成非抽象组件,如下图,你可以看到keep-alive内部参数)只有name在这个数组中的组件才会被缓存,不然会把对应的已缓存的组件实例销毁。key是组件缓存用来保存缓存组件实例用的key值,当你点击tag时,会根据对应的key取出对应的组件实例进行显示(具体看源码吧,或者别的解析文章,这个原理一定要懂,不然后面的内容可能不太容易理解)

js 复制代码
// keep-alive缓存源码
// 地址:https://github.com/vuejs/vue/blob/main/src/core/components/keep-alive.ts#L69
cacheVNode() {
  const { cache, keys, vnodeToCache, keyToCache } = this
  if (vnodeToCache) {
    const { tag, componentInstance, componentOptions } = vnodeToCache
    cache[keyToCache] = {
      name: _getComponentName(componentOptions),
      tag,
      componentInstance
    }
    keys.push(keyToCache)
    // prune oldest entry
    if (this.max && keys.length > parseInt(this.max)) {
      pruneCacheEntry(cache, keys[0], keys, this._vnode)
    }
    this.vnodeToCache = null
  }
}
},

问题:关闭tag会导致动态路由页面缓存失效

由此可见,动态路由keep-alive是可以缓存的,你传入的key为路由的path就行,但是呢,我们因为做了多页签处理,所以就碰到一个很难受的问题,keep-alive的include的数组保存的组件name,动态路由只是path不一样,但是name是一样的,所以当你关闭一个tag时,会删除页签数组中的对应的组件的name,而这个数组是传入到keep-alive的include的数组,那这样会把name相同但是path不同的组件全都销毁了,缓存就会失效。

微前端多页签缓存方案解析(简洁版)

现在的主应用布局组件Layout结构如下图:

  • 解释一下:layout组件是主应用使用的布局组件,tag-view是多页签组件,AppMain是包裹子应用的主内容区组件。目前layout组件为了实现缓存页面,在 app-main 主内容区有keep-alive 组件,要在多层路由中都能缓存则需要多层 keep-alive 组件(注意:子主应用各自有自己的一套路由,比如编辑页面,主应用编辑页路由name是Edit,子应用编辑页路由的name也是Edit,它俩的path要一致),所以子应用也有对应的keep-alive包裹。
  • 当主应用删除一个tag时,会删除对应的组件name,并且会将删除的组件的path通知到子应用,子应用拿到path找到对应组件的name,将缓存的include中的name删除。
  • 问题来了,动态路由name是一样的呀,上面有说到,就是你打开多个编辑页,你只要删了其中一个tag,那就会触发多次组件销毁,并通知多次到子应用,子组件对应的也是会去删除include中的name,也会导致缓存直接失效了。

解决方案

主应用:

  1. 继承keep-alive组件,创建KeepAliveManuallyCache组件,设置组件为非抽象组件,设置ref,并在内部封装一个函数clearCacheByKey(参数是route的path),这个函数的作用是用于手动删除缓存
  2. tag关闭时,抛出一个删除事件到layout组件,监听这个方法,删除事件触发时,拿到KeepAliveManuallyCache的ref,并调用clearCacheByKey,销毁对应path的组件实例(clearCacheByKey的实现参考keep-alive源码中的pruneCacheEntry的方法)
  3. 设置一个标志,在使用KeepAliveManuallyCache组件进行显示时,不要去删除对应的缓存中的组件name(删了缓存就失效了,理由上面有说)
  4. 在原来使用keep-alive的地方,使用component 组件渲染,暴露keepAliveName字段,让用户自主传入keep-alive的名称,进行渲染

子应用:

  1. 因为keep-alive是根据include的值name去决定组件缓存的,不在include中的组件,会被销毁,所以子组件更简单一点的解决方案是,动态添加路由,在点击编辑进行跳转之前将编辑页组件的name重写,生成动态的name的组件,比如Edit-${id},这样在关闭tag的时候,由于每个编辑页的name是唯一的,所以不会把所有的编辑页的实例给销毁
  2. 预览页同上
  3. 其实主应用也可以采用1的方案,但是主应用有很多子应用页面,不可能每个都那么处理的

这样问题就解决了,嘿嘿嘿!!!

最后,感谢大家阅读我的小文章,请帮我点亮一下我的小心心吧!!!

相关推荐
并不会38 分钟前
常见 CSS 选择器用法
前端·css·学习·html·前端开发·css选择器
衣乌安、41 分钟前
【CSS】居中样式
前端·css·css3
兔老大的胡萝卜42 分钟前
ppk谈JavaScript,悟透JavaScript,精通CSS高级Web,JavaScript DOM编程艺术,高性能JavaScript pdf
前端·javascript
低代码布道师44 分钟前
CSS的三个重点
前端·css
耶啵奶膘2 小时前
uniapp-是否删除
linux·前端·uni-app
王哈哈^_^4 小时前
【数据集】【YOLO】【目标检测】交通事故识别数据集 8939 张,YOLO道路事故目标检测实战训练教程!
前端·人工智能·深度学习·yolo·目标检测·计算机视觉·pyqt
cs_dn_Jie4 小时前
钉钉 H5 微应用 手机端调试
前端·javascript·vue.js·vue·钉钉
开心工作室_kaic5 小时前
ssm068海鲜自助餐厅系统+vue(论文+源码)_kaic
前端·javascript·vue.js
有梦想的刺儿5 小时前
webWorker基本用法
前端·javascript·vue.js
cy玩具5 小时前
点击评论详情,跳到评论页面,携带对象参数写法:
前端