Ant Design Vue Pro(V3.0.0 )MultiTab标签缓存,完美解决

使用Ant Design Vue Pro 基础框架都知道好用,但是MultiTab标签一直未解决(V3.0.0),最新版解决了但是要收费9K(2022-01-21日)。
首先需要实现如下:
在这里插入图片描述
MultiTab标签打开菜单路由页面之后keep-alive就一直保持缓存当前路由页面,直到点击MultiTab标签的X(或者点击菜单:关闭当前/关闭左边/关闭右边/关闭全部)此时删除keep-alive缓存。下次重新打开时候重新缓存菜单路由页面到keep-alive并再次保持缓存。

这里有个注意的地方有的菜单路由页面没有在左边菜单里面,比如详情页(需要参数传递)不需要keep-alive缓存,每次必须按照参数初始化渲染。

解决:

  • 痛点①:关闭当前页时候怎么删除当前页在keep-alive的缓存?
  • 痛点②:关闭非当前页怎么删除它们在keep-alive的缓存?
  • 痛点③:怎么剔除掉不在左边菜单里面的路由页,不让keep-alive缓存?

我的方案:

  • 请保证views目录下每个路由页面有唯一的:name(这样做最大限度减少MultiTab标签的错误率,原因:keep-alive依赖路由组件的name做缓存)
    在这里插入图片描述

第一步step1:

  • 开启keep-alive
    位置:src\config\defaultSettings.js
    在这里插入图片描述

位置: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 = (
  //     <keep-alive>
  //       <router-view />
  //     </keep-alive>
  //   )
  //   const notKeep = (
  //       <router-view />
  //   )
  //   // 这里增加了 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

  • 11
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 22
    评论
评论 22
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值