使用Ant Design Vue Pro 基础框架都知道好用,但是MultiTab标签一直未解决(V3.0.0),最新版解决了但是要收费9K(2022-01-21日)。
首先需要实现如下:
MultiTab标签打开菜单路由页面之后keep-alive就一直保持缓存当前路由页面,直到点击MultiTab标签的X(或者点击菜单:关闭当前/关闭左边/关闭右边/关闭全部)此时删除keep-alive缓存。下次重新打开时候重新缓存菜单路由页面到keep-alive并再次保持缓存。
这里有个注意的地方有的菜单路由页面没有在左边菜单里面,比如详情页(需要参数传递)不需要keep-alive缓存,每次必须按照参数初始化渲染。
解决:
我的方案:
第一步step1:
位置:src\layouts\RouteView.vue
<template>
<keep-alive :exclude="keepAliveListExcludeNames">
<router-view />
keep-alive>
template>
<script>
export default {
name: 'RouteView',
props: {
keepAlive: {
type: Boolean,
default: true
}
},
data () {
return {}
},
computed:{
keepAliveListExcludeNames(){
let kpen = this.$store.state.app.keepAliveListExcludeNames
//痛点③:怎么剔除掉不在左边菜单里面的路由页,不让keep-alive缓存?
console.log('获取缓存的keepAliveListExcludeNames列表',kpen)
return kpen;
}
}
// render () {
// const { $route: { meta }, $store: { getters } } = this
// const inKeep = (
//
//
//
// )
// const notKeep = (
//
// )
// // 这里增加了 multiTab 的判断,当开启了 multiTab 时
// // 应当全部组件皆缓存,否则会导致切换页面后页面还原成原始状态
// // 若确实不需要,可改为 return meta.keepAlive ? inKeep : notKeep
// if (!getters.multiTab && !meta.keepAlive) {
// return notKeep
// }
// return this.keepAlive || getters.multiTab || meta.keepAlive ? inKeep : notKeep
// }
}
script>
位置:src\store\modules\app.js
//此处省略前面代码便于讲解
state: {
//此处省略前面代码便于讲解
keepAliveListExcludeNames:'',//痛点③:怎么剔除掉不在左边菜单里面的路由页,不让keep-alive缓存?
},
//此处省略前面代码便于讲解
mutations: {
//此处省略前面代码便于讲解
setKeepAliveListExcludeNames(state,keepAliveListExcludeNamesString){
state.keepAliveListExcludeNames = keepAliveListExcludeNamesString
},
},
//此处省略后面代码便于讲解
位置:src\config\router.config.js(静态路由)
位置:src\router\generator-routers.js(动态路由)
第二步step2:
位置:src\main.js(放在创建Vue实例前面)
//使用Vue.mixin的方法拦截了路由事件、keep-alive事件
window.current_component_globle_remove = false
window.current_component_globle_remove_list = []
window.current_component_globle_remove_step_2_2 = null
window.current_component_globle_level_params_route = null
Vue.mixin({
//keep-alive事件
activated(){
//痛点③:怎么剔除掉不在左边菜单里面的路由页,不让keep-alive缓存?
//路由页面需要参数:说明是非左边菜单路由页面,如:详情页
if(this.$route && this.$route.params && JSON.stringify(this.$route.params) !="{}"
&& window.current_component_globle_level_params_route == this.$route.path
&& this.$vnode
&& this.$vnode.data.keepAlive){
let on = this.$options.name
let tempKp = this.$store.state.app.keepAliveListExcludeNames
if(tempKp && tempKp.length > 0){
tempKp = tempKp.split(",")
let kpf = tempKp.find((item)=>{
return item == on
})
//还没有加入keepAliveListExcludeNames
if(!kpf){
tempKp.push(on)
this.$store.commit('setKeepAliveListExcludeNames',tempKp.join())
}
}else{
this.$store.commit('setKeepAliveListExcludeNames',[on].join())
}
}
// 痛点②:关闭非当前页怎么删除它们在keep-alive的缓存?
if (!window.current_component_globle_remove){
let findName_ = window.current_component_globle_remove_list.find((item)=>{
return item == this.$route.path
})
if(findName_){
if (this.$vnode && this.$vnode.data.keepAlive){
// 重置不是当前页面关闭
window.current_component_globle_remove = false
window.current_component_globle_remove_list =
window.current_component_globle_remove_list.filter((item)=>{
return item != this.$route.path
});
// 删除keep-alive的缓存
if (this.$vnode.parent && this.$vnode.parent.componentInstance && this.$vnode.parent.componentInstance.cache)
{
if (this.$vnode.componentOptions)
{
var key = this.$vnode.key == null
? this.$vnode.componentOptions.Ctor.cid + (this.$vnode.componentOptions.tag ? `::${this.$vnode.componentOptions.tag}` : '')
: this.$vnode.key;
var cache = this.$vnode.parent.componentInstance.cache;
var keys = this.$vnode.parent.componentInstance.keys;
if (cache[key])
{
if (keys.length) {
var index = keys.indexOf(key);
if (index > -1) {
keys.splice(index, 1);
}
}
delete cache[key];
}
}
}
//删除非当前页
this.$destroy();
console.log("step:2-2")
//再一次进入
// 怎么关闭当前multitale页面??
// --①先往回跳转
if(window.current_component_globle_remove_step_2_2){
//--②再跳转回来
let temp = window.current_component_globle_remove_step_2_2
window.current_component_globle_remove_step_2_2 = this.$route.path
this.$router.push({path:temp})
}
}
}
else{
//--③再跳转回来
if(window.current_component_globle_remove_step_2_2){
let temp_ = window.current_component_globle_remove_step_2_2
window.current_component_globle_remove_step_2_2 = null
this.$router.push({path:temp_})
}
}
}
},
beforeRouteUpdate:function(to, from, next){
// 痛点②:关闭非当前页怎么删除它们在keep-alive的缓存?
if (!window.current_component_globle_remove){
let findName_ = window.current_component_globle_remove_list.find((item)=>{
return item == to.path
})
// //被当前页面关闭过,现在要打开关闭的页面
if(findName_){
//清除keep-alive和组件,重新初始化
console.log("step:2")
//转:activated
window.current_component_globle_remove_step_2_2 = from.name
}
// //没有被当前页面关闭过,当前页面跳转
else{
//TODO
console.log("step:3")
}
next();
}
},
beforeRouteLeave:function(to, from, next){
//痛点①:关闭当前页时候怎么删除当前页在keep-alive的缓存?
if(window.current_component_globle_remove){
let findName = window.current_component_globle_remove_list.find((item)=>{
return item == from.path
})
//from就是关闭的页面
if(findName){
//删除关闭页面的keep-alive
if (this.$vnode && this.$vnode.data.keepAlive)
{
if (this.$vnode.parent && this.$vnode.parent.componentInstance && this.$vnode.parent.componentInstance.cache)
{
if (this.$vnode.componentOptions)
{
var key = this.$vnode.key == null
? this.$vnode.componentOptions.Ctor.cid + (this.$vnode.componentOptions.tag ? `::${this.$vnode.componentOptions.tag}` : '')
: this.$vnode.key;
var cache = this.$vnode.parent.componentInstance.cache;
var keys = this.$vnode.parent.componentInstance.keys;
if (cache[key])
{
if (keys.length) {
var index = keys.indexOf(key);
if (index > -1) {
keys.splice(index, 1);
}
}
delete cache[key];
}
}
}
}
//删除关闭页面
this.$destroy();
//重置不是当前页面关闭
window.current_component_globle_remove = false
window.current_component_globle_remove_list =
window.current_component_globle_remove_list.filter((item)=>{
return item != from.path
});
console.log("step:1")
}else{
window.current_component_globle_remove = false
console.log("step:1-no")
}
}
next();
}
});
//放在创建Vue实例前面
new Vue({
router,
store,
i18n,
created: bootstrap,
render: h => h(App)
}).$mount('#app')
位置:src\permission.js
router.afterEach((route ) => {
//省略非关键性代码
console.log("进入后" ,route.path,route.params)
window.current_component_globle_level_params_route = route.path
})
位置:src\components\MultiTab\MultiTab.vue
console.log("remove",targetKey)
window.current_component_globle_remove = this.$route.path == targetKey ? true : false
window.current_component_globle_remove_list.push(targetKey)
感谢:
https://segmentfault.com/a/1190000015845117