应用场景
当系统打开多个页签时,多个页签之间切换去做缓存,关闭页签重新打开该页签不缓存。
解决方案
更改 vue keep-alive源码
1、制造一个唯一的key值,在路由参数里面加一个时间戳
1.1 因keep-alive 使用组件名称name值作为唯一的key值去做条件缓存,但是该项目因书写不规范导致组件的name值不是唯一的。在路由的参数
里面增加一个时间戳
// 当点击系统左侧菜单的时候加时间戳
select(url) {
//先把打开的页签全部放到store里面
//在打开页签里面找index原因是:找到已经打开过的页签的index,避免打开重复的多个页签
const isHas = this.$store.state.multiTabPages.findIndex((val)=>{
return val.name === url
})
if(isHas === -1) {
this.$router.push({name:url, query: {
timeStr: new Date().getTime()
}});
}else {
//如果找到已经打开过的这个页签,那就跳转到它原来的最初打开的页签页面
this.$router.push({name:url, query: {
timeStr: this.$store.state.multiTabPages[isHas].query.timeStr
}});
}
},
2、给自定义的keep-alive组件唯一的key值
2.1 从依赖vue包里面找到keep-alive组件,拿到源码。在全局的组件里面创建一个自定义的keep-alive组件,注意组件名不要和vue自带的keep-alive组件名称相同会有冲突。
2.2 源码是用ts写的,如果你的项目不支持ts,要先改成js,主要改的是render里面的逻辑。
// keep-alive使用的是name值做匹配缓存,如下:
const name = getComponentName(componentOptions)
const { include, exclude } = this
if (
// not included
(include && (!name || !matches(include, name))) ||
// excluded
(exclude && name && matches(exclude, name))
) {
return vnode
}
const { cache, keys } = this
const key = vnode.key == null
// same constructor may get registered as different local components
// so cid alone is not enough (#3269)
? componentOptions.Ctor.cid + (componentOptions.tag ? `::${componentOptions.tag}` : '')
: vnode.key
2.3 把关闭页签的路由信息存入store中,在自定义的keep-alive组件中拿到关闭页签的路由信息
const slot = this.$slots.default // 获取默认插槽
const vnode = getFirstComponentChild(slot) // 获取第一个子节点
const componentOptions = vnode && vnode.componentOptions
if (componentOptions) {
const { cache, keys } = this
const route = this.$route
const key = route.fullPath //拿到打开的页签的唯一key值(在路由里面加的时间戳和path组成的一个唯一的key值)
// 拿到关闭页签的路由信息
const removeRoute = this.$store.state.removeRoute || []
if(removeRoute && removeRoute.length > 0){
let tempKeys = JSON.parse(JSON.stringify(this.keys))
let diff = tempKeys.filter((val) => { return !removeRoute.includes(val)})
this.keys = JSON.parse(JSON.stringify(diff))
for (const key in this.cache) {
// 在缓存的cache对象里面移除掉已关闭的页签的信息
if(removeRoute.includes(key)) {
delete this.cache[key];
}
}
}
// 如果key对应的vnode存在,则更新key值
if (cache[key]) {
vnode.componentInstance = cache[key].componentInstance
remove(keys, key)
keys.push(key) // 调整key排序
} else {
// 否则将v