4
0
mirror of https://github.com/iczer/vue-antd-admin.git synced 2025-04-06 03:57:44 +08:00
vue-antd-admin/src/layouts/TabsView.vue
iczer 255f68709e fix: solve the cache problem in multi tabs mode; 🐛
修复: 解决多页签模式下的内存泄露问题;
2020-07-10 21:48:29 +08:00

199 lines
6.5 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<template>
<admin-layout>
<contextmenu :itemList="menuItemList" :visible.sync="menuVisible" @select="onMenuSelect" />
<a-tabs
@contextmenu.native="e => onContextmenu(e)"
v-if="multiPage"
:active-key="activePage"
:style="`margin: -16px auto 8px; ${layout == 'head' ? 'max-width: 1400px;' : ''}`"
:hide-add="true"
type="editable-card"
@change="changePage"
@edit="editPage">
<a-tab-pane :key="page.fullPath" v-for="page in pageList">
<span slot="tab" :pagekey="page.fullPath">{{page.name}}</span>
</a-tab-pane>
</a-tabs>
<div class="tabs-view-content">
<page-toggle-transition :disabled="animate.disabled" :animate="animate.name" :direction="animate.direction">
<keep-alive :exclude="dustbins" v-if="multiPage">
<router-view />
</keep-alive>
<router-view v-else />
</page-toggle-transition>
</div>
</admin-layout>
</template>
<script>
import AdminLayout from './AdminLayout'
import Contextmenu from '../components/menu/Contextmenu'
import PageToggleTransition from '../components/transition/PageToggleTransition'
import {mapState, mapMutations} from 'vuex'
export default {
name: 'TabsView',
components: {PageToggleTransition, Contextmenu, AdminLayout},
data () {
return {
pageList: [],
activePage: '',
menuVisible: false,
menuItemList: [
{ key: '1', icon: 'arrow-left', text: '关闭左侧' },
{ key: '2', icon: 'arrow-right', text: '关闭右侧' },
{ key: '3', icon: 'close', text: '关闭其它' }
]
}
},
computed: {
...mapState('setting', ['multiPage', 'animate', 'layout', 'dustbins'])
},
created () {
const route = this.$route
this.pageList.push(route)
this.activePage = route.fullPath
},
watch: {
'$route': function (newRoute) {
this.activePage = newRoute.fullPath
this.putCache(newRoute)
if (!this.multiPage) {
this.pageList = [newRoute]
} else if (this.pageList.findIndex(item => item.fullPath == newRoute.fullPath) == -1) {
this.pageList.push(newRoute)
}
},
'multiPage': function (newVal) {
if (!newVal) {
this.pageList = [this.$route]
}
}
},
methods: {
changePage (key) {
this.activePage = key
this.$router.push(key)
},
editPage (key, action) {
this[action](key)
},
remove (key) {
if (this.pageList.length === 1) {
this.$message.warning('这是最后一页,不能再关闭了啦')
return
}
let index = this.pageList.findIndex(item => item.fullPath == key)
let pageRoute = this.pageList[index]
this.clearCache(pageRoute)
this.pageList = this.pageList.filter(item => item.fullPath !== key)
if (key == this.activePage) {
index = index >= this.pageList.length ? this.pageList.length - 1 : index
this.activePage = this.pageList[index].fullPath
this.$router.push(this.activePage)
}
},
onContextmenu (e) {
const pageKey = this.getPageKey(e.target)
if (pageKey !== null) {
e.preventDefault()
this.menuVisible = true
}
},
/**
* 由于ant-design-vue组件库的TabPane组件暂不支持自定义监听器无法直接获取到右键target所在标签页的 pagekey 。故增加此方法用于
* 查询右键target所在标签页的标识 pagekey ,以用于自定义右键菜单的事件处理。
* 注TabPane组件支持自定义监听器后可去除该方法并重构 ‘自定义右键菜单的事件处理’
* @param target 查询开始目标
* @param count 查询层级深度 查找层级最多不超过3层超过3层深度直接返回 null
* @returns {String}
*/
getPageKey (target, depth) {
depth = depth || 0
if (depth > 2) {
return null
}
let pageKey = target.getAttribute('pagekey')
pageKey = pageKey || (target.previousElementSibling ? target.previousElementSibling.getAttribute('pagekey') : null)
return pageKey || (target.firstElementChild ? this.getPageKey(target.firstElementChild, ++depth) : null)
},
onMenuSelect (key, target) {
let pageKey = this.getPageKey(target)
switch (key) {
case '1':
this.closeLeft(pageKey)
break
case '2':
this.closeRight(pageKey)
break
case '3':
this.closeOthers(pageKey)
break
default:
break
}
},
closeOthers (pageKey) {
const index = this.pageList.findIndex(item => item.fullPath == pageKey)
// 要关闭的页面清除缓存
this.pageList.forEach(item => {
if (item.fullPath != pageKey){
this.clearCache(item)
}
})
this.pageList = this.pageList.slice(index, index + 1)
this.activePage = this.pageList[0].fullPath
this.$router.push(this.activePage)
},
closeLeft (pageKey) {
const index = this.pageList.findIndex(item => item.fullPath == pageKey)
// 清除缓存
this.pageList.forEach((item, i) => {
if (i < index) {
this.clearCache(item)
}
})
this.pageList = this.pageList.slice(index)
if (this.pageList.findIndex(item => item.fullPath == this.activePage) == -1) {
this.activePage = this.pageList[0].fullPath
this.$router.push(this.activePage)
}
},
closeRight (pageKey) {
const index = this.pageList.findIndex(item => item.fullPath == pageKey)
// 清除缓存
this.pageList.forEach((item, i) => {
if (i > index) {
this.clearCache(item)
}
})
this.pageList = this.pageList.slice(0, index + 1)
if (this.pageList.findIndex(item => item.fullPath == this.activePage) == -1) {
this.activePage = this.pageList[this.pageList.length - 1].fullPath
this.$router.push(this.activePage)
}
},
clearCache(route) {
const componentName = route.matched.slice(-1)[0].components.default.name
if (this.dustbins.findIndex(item => item == componentName) == -1) {
this.setDustbins(this.dustbins.concat(componentName))
}
},
putCache(route) {
const componentName = route.matched.slice(-1)[0].components.default.name
if (this.dustbins.findIndex(item => item == componentName) != -1) {
this.setDustbins(this.dustbins.filter(item => item != componentName))
}
},
...mapMutations('setting', ['setDustbins'])
}
}
</script>
<style scoped lang="less">
.tabs-view-content{
position: relative;
}
</style>