由于admin项目里面有2个菜单使用了
meta: {title: "绩效汇总", icon: "nested", keepAlive: true},
在测试的时候,打开2个keepAlive都开启的菜单,在点击上面的标签页关闭,在重新打开,会将本来没有在B缓存页面的内容突然存在了A缓存页面的内容,后经过排查是因为2个缓存共用的原因导致,如果没有关闭上面的标签页就没有该BUG产生。
开始了第一次尝试。
当点关闭标签的时候如果不想当前页面缓存 加上
接着遇到了第一次缓存第二次改为false后打开不缓存了 在关闭标签页面 加上这个
watch: {
$route() {
if (this.$route.meta.keepAlive==false) {
this.$route.meta.keepAlive=true
}
},
尝试后没过效果,还是有缓存。
第2个方案
下面是vue的keep-alive.js的源码
function pruneCacheEntry (cache,key,keys,current) {
const cached = cache[key]
if (cached && (!current || cached.tag !== current.tag)) {
cached.componentInstance.$destroy()
}
cache[key] = null
remove(keys, key)
}
可以看到1、调用destory() 2、清空cache 3、移除kes里对应的key值
我们通过这个方法可以修改layout/components/AppMain.vue
把keep-alive里面的 cachedViews方法去掉。引入bus。
<template>
<section class="app-main">
<transition name="fade-transform" mode="out-in">
<keep-alive :max="20">
<router-view :key="key" />
</keep-alive>
</transition>
</section>
</template>
<script>
import Bus from '../bus.js'
export default {
name: 'AppMain',
computed: {
cachedViews() {
return this.$store.state.tagsView.cachedViews;
},
key() {
return this.$route.fullPath;
}
},
mounted() {
// 关闭标签触发
Bus.$on('removeCache', (name, view) => {
this.removeCache(name, view);
});
},
methods: {
// 获取有keep-alive子节点的Vnode
getVnode() {
// 判断子集非空
if (this.$children.length == 0) return false;
let vnode;
for (let item of this.$children) {
// 如果data中有key则代表找到了keep-alive下面的子集,这个key就是router-view上的key
if (item.$vnode.data.key) {
vnode = item.$vnode;
break;
}
}
return vnode ? vnode : false;
},
// 移除keep-alive缓存
removeCache(name, view = {}) {
let vnode = this.getVnode();
if (!vnode) return false;
let componentInstance = vnode.parent.componentInstance;
// 这个key是用来获取前缀用来后面正则匹配用的
let keyStart = vnode.key.split('/')[0];
let thisKey = `${keyStart}${view.fullPath}`;
let regKey = `${keyStart}${view.path}`;
this[name]({ componentInstance, thisKey, regKey });
},
// 移除其他
closeOthersTags({ componentInstance, thisKey }) {
Object.keys(componentInstance.cache).forEach((key, index) => {
if (key != thisKey) {
// 1 销毁实例(这里存在多个key指向一个缓存的情况可能前面一个已经清除掉了所有要加判断)
if (componentInstance.cache[key]) {
componentInstance.cache[key].componentInstance.$destroy();
}
// 2 删除缓存
delete componentInstance.cache[key];
// 3 移除key中对应的key
componentInstance.keys.splice(index, 1);
}
});
},
// 移除所有缓存
closeAllTags({ componentInstance }) {
// 1 销毁实例
Object.keys(componentInstance.cache).forEach(key => {
if (componentInstance.cache[key]) {
componentInstance.cache[key].componentInstance.$destroy();
}
});
// 2 删除缓存
componentInstance.cache = {};
// 3 移除key中对应的key
componentInstance.keys = [];
},
// 移除单个缓存
closeSelectedTag({ componentInstance, regKey }) {
let reg = new RegExp(`^${regKey}`);
Object.keys(componentInstance.cache).forEach((key, i) => {
if (reg.test(key)) {
// 1 销毁实例
if (componentInstance.cache[key]) {
componentInstance.cache[key].componentInstance.$destroy();
}
// 2 删除缓存
delete componentInstance.cache[key];
// 3 移除key中对应的key
componentInstance.keys.splice(i, 1);
}
});
}
}
};
</script>
引入bus,用bus触发一下方法,修改layout/components/TagsView.vue
closeSelectedTag(view) {
this.$store.dispatch("delView", view).then(({ visitedViews }) => {
if (this.isActive(view)) {
const latestView = visitedViews.slice(-1)[0];
if (latestView) {
this.$router.push(latestView);
} else {
this.$router.push("/");
}
}
//关闭单个
Bus.$emit('removeCache','closeSelectedTag',view)
});
},
closeOthersTags() {
this.$router.push(this.selectedTag);
//关闭其他
Bus.$emit('removeCache','closeOthersTags',this.selectedTag);
this.$store.dispatch("delOthersViews", this.selectedTag).then(() => {
this.moveToCurrentTag();
});
},
closeAllTags(view) {
this.$store.dispatch("delAllViews").then(({ visitedViews }) => {
this.toLastView(visitedViews, view);
//关闭所有
Bus.$emit('removeCache','closeAllTags')
});
},
beforeDestory(){
Bus.$off('removeCache')
}