ant design vue pro项目中,选择多页签模式,会通过项目中的RouteView组件,利用keep-alive对打开的组件进行缓存,方便切换标签时,使组件保存当时的状态。
但这样会对所有组件都进行缓存,即使通过标签页关闭后。
MultiTab组件里的关闭,其实只是删除了标签,使不能再通过标签打开组件。
想达到的目的是切换标签时,组件保持状态;关闭标签后,再打开组件时,组件是新状态。
应用场景:
例如:侧边栏打开 ‘人员列表’,在改组件中有个按钮 ‘新增人员’,点击后打开 ‘新增人员’组件。
此时有俩标签 ‘人员列表’、 ‘新增人员’,切换时都保持状态。‘新增人员’ 中输入内容后,通过标签关闭,由于keep-alive的缓存,在次从 ‘人员列表’ 中打开 ‘新增人员’, 之前输入的东西都还在 ┭┮﹏┭┮
尝试过,‘新增人员’activated时,将本身实例传入MultiTab中保存,但通过标签关闭时,在MultiTab中找到对应实例使用$destroy(),这样再打开就会重新生成实例。
但悲剧的是,这样操作后(关闭后再打开),在切换标签时,每次切到之前销毁的那个组件,该组件就会新生成一个实例
完全懵逼了,不晓得怎么处理,求大佬搭救,给个思路。
###在打开页面时验证多标签页中是否存在要打开的这个页面,如果存在则不需要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>
###问一下,怎么配置多标签页的