ant design vue pro 多页签模式下,根据需求进行组件缓存

ant design vue pro项目中,选择多页签模式,会通过项目中的RouteView组件,利用keep-alive对打开的组件进行缓存,方便切换标签时,使组件保存当时的状态。
但这样会对所有组件都进行缓存,即使通过标签页关闭后。
MultiTab组件里的关闭,其实只是删除了标签,使不能再通过标签打开组件。

想达到的目的是切换标签时,组件保持状态;关闭标签后,再打开组件时,组件是新状态。

应用场景:
例如:侧边栏打开 ‘人员列表’,在改组件中有个按钮 ‘新增人员’,点击后打开 ‘新增人员’组件。
此时有俩标签 ‘人员列表’、 ‘新增人员’,切换时都保持状态。‘新增人员’ 中输入内容后,通过标签关闭,由于keep-alive的缓存,在次从 ‘人员列表’ 中打开 ‘新增人员’, 之前输入的东西都还在 ┭┮﹏┭┮

尝试过,‘新增人员’activated时,将本身实例传入MultiTab中保存,但通过标签关闭时,在MultiTab中找到对应实例使用$destroy(),这样再打开就会重新生成实例。
但悲剧的是,这样操作后(关闭后再打开),在切换标签时,每次切到之前销毁的那个组件,该组件就会新生成一个实例

完全懵逼了,不晓得怎么处理,求大佬搭救,给个思路。

阅读 10.1k
3 个回答

在打开页面时验证多标签页中是否存在要打开的这个页面,如果存在则不需要activeted更新数据,如果不存在则使用activeted更新页面数据

找到一个思路,利用keep-alive的include,结合Vuex。
总思路就是动态的改变include的内容,include的值来源于stroe中
新打开的标签页,将页面组件名存在stroe,include同步改变,这样切换标签页就保持页面组件状态。
标签页关闭,则在stroe中删除该页面组件名,include同步改变后,将不会在keep-alive中进行缓存

我这里,页面组件名与路由名一样,这样方便在MultiTab.vue里面操作(不晓得页面组件名能不能通过获取路由名来设置,不然就只能先写好,这有点瓜...)

另外,求助大侠们,有没可以限制打开页面组件个数的思路??

废话不多说,直接上代码...

store.js

export default new Vuex.Store({
  state: {
    keepAliveInclude: []
  },
  mutations: {
    setKeepAliveInclude(state, data){
      if(data.type === 'add'){
        state.keepAliveInclude.push(data.name)
      }
      if(data.type === 'delete'){
        let index = state.keepAliveInclude.indexOf(data.name); 
        if (index > -1) { 
          state.keepAliveInclude.splice(index, 1); 
        } 
      }
    }
  },
  actions: {
    refreshKeepAliveInclude (context, data) {
      context.commit('setKeepAliveInclude', data)
    }
  }
});
MultiTab.vue

created () {
    ...
    this.$store.dispatch('refreshKeepAliveInclude', {
      name: this.$route.name,
      type: 'add'
    })
    // 用于RouteView里面有嵌套一层RouteView
    if(this.$route.meta.hasRouteView){
      this.$store.dispatch('refreshKeepAliveInclude', {
        name: 'RouteView',
        type: 'add'
      });
    }
    ...
},
methods: {
    remove (targetKey) {
      let targetPage = this.pages.find(page => page.fullPath === targetKey);
      this.$store.dispatch('refreshKeepAliveInclude', {
        name: targetPage.name,
        type: 'delete'
      })
      // 用于RouteView里面有嵌套一层RouteView
      if(targetPage.meta.hasRouteView){
        this.$store.dispatch('refreshKeepAliveInclude', {
          name: 'RouteView',
          type: 'delete'
        });
      }
      ...
    }
 }
  watch: {
    '$route': function (newVal) {      
      if (this.fullPathList.indexOf(newVal.fullPath) < 0) {
        this.fullPathList.push(newVal.fullPath)
        this.pages.push(newVal);

        this.$store.dispatch('refreshKeepAliveInclude', {
          name: newVal.name,
          type: 'add'
        });
        if(newVal.meta.hasRouteView){
          this.$store.dispatch('refreshKeepAliveInclude', {
            name: 'RouteView',
            type: 'add'
          });
        }
      }
      this.activeKey = newVal.fullPath
    },
    ...
  },
RouteView.vue

<script>
export default {
  name: 'RouteView',
  props: {
    keepAlive: {
      type: Boolean,
      default: true
    }
  },
  data () {
    return {
      keepAliveInclude: this.$store.state.keepAliveInclude
    }
  },
  render () {
    const inKeep = (
      <keep-alive include={this.keepAliveInclude}>
        <router-view />
      </keep-alive>
    )
    return inKeep
  }
}
</script>
新手上路,请多包涵

问一下,怎么配置多标签页的

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题
宣传栏