feat: add function of refreshing page; #132

新增:刷新页面的功能;
This commit is contained in:
chenghongxing 2020-09-30 19:39:26 +08:00
parent 83576d88d7
commit 313af63f33
5 changed files with 102 additions and 51 deletions

View File

@ -33,6 +33,7 @@ export default {
left: 0,
top: 0,
target: null,
meta: null,
selectedKeys: []
}
},
@ -45,14 +46,12 @@ export default {
}
},
created () {
const clickHandler = () => this.closeMenu()
const contextMenuHandler = e => this.setPosition(e)
window.addEventListener('click', clickHandler)
window.addEventListener('contextmenu', contextMenuHandler)
this.$emit('hook:beforeDestroy', () => {
window.removeEventListener('click', clickHandler)
window.removeEventListener('contextmenu', contextMenuHandler)
})
window.addEventListener('click', this.closeMenu)
window.addEventListener('contextmenu', this.setPosition)
},
beforeDestroy() {
window.removeEventListener('click', this.closeMenu)
window.removeEventListener('contextmenu', this.setPosition)
},
methods: {
closeMenu () {
@ -62,9 +61,10 @@ export default {
this.left = e.clientX
this.top = e.clientY
this.target = e.target
this.meta = e.meta
},
handleClick ({ key }) {
this.$emit('select', key, this.target)
this.$emit('select', key, this.target, this.meta)
this.closeMenu()
}
}

View File

@ -5,9 +5,6 @@
:class="['tabs-container', layout, pageWidth, {'affixed' : affixed, 'fixed-header' : fixedHeader, 'collapsed' : adminLayout.collapsed}]"
:active-key="active"
:hide-add="true"
@change="onChange"
@edit="onEdit"
@contextmenu="onContextmenu"
>
<a-tooltip placement="left" :title="lockTitle" slot="tabBarExtraContent">
<a-icon
@ -18,7 +15,11 @@
/>
</a-tooltip>
<a-tab-pane v-for="page in pageList" :key="page.fullPath">
<span slot="tab" :pagekey="page.fullPath">{{pageName(page)}}</span>
<div slot="tab" class="tab" @contextmenu="e => onContextmenu(page.fullPath, e)">
<a-icon v-if="page.fullPath === active || page.loading" @click="onRefresh(page)" class="icon-sync" :type="page.loading ? 'loading' : 'sync'" />
<span @click="onTabClick(page.fullPath)" >{{pageName(page)}}</span>
<a-icon @click="onClose(page.fullPath)" class="icon-close" type="close"/>
</div>
</a-tab-pane>
</a-tabs>
<div v-if="affixed" class="virtual-tabs"></div>
@ -58,11 +59,6 @@
}
},
inject:['adminLayout'],
watch: {
'adminLayout.collapsed': (val) => {
console.log(val)
}
},
created() {
this.affixed = this.fixedTabs
},
@ -84,16 +80,19 @@
this.affixed = false
}
},
onChange(key) {
onTabClick(key) {
if (this.active !== key) {
this.$emit('change', key)
},
onEdit(key, action) {
if (action === 'remove') {
this.$emit('close', key)
}
},
onContextmenu(e) {
this.$emit('contextmenu', e)
onClose(key) {
this.$emit('close', key)
},
onRefresh(page) {
this.$emit('refresh', page.fullPath, page)
},
onContextmenu(pageKey, e) {
this.$emit('contextmenu', pageKey, e)
},
pageName(page) {
return this.$t(getI18nKey(page.keyPath))
@ -103,6 +102,28 @@
</script>
<style scoped lang="less">
.tab{
margin: 0 -16px;
padding: 0 16px;
font-size: 14px;
user-select: none;
.icon-close{
font-size: 12px;
margin-left: 6px;
margin-right: -4px;
color: @text-color-second;
&:hover{
color: @text-color;
}
}
.icon-sync{
margin-left: -4px;
color: @primary-4;
&:hover{
color: @primary-color;
}
}
}
.tabs-head{
margin: 0 auto;
&.head.fixed{

View File

@ -7,12 +7,13 @@
:page-list="pageList"
@change="changePage"
@close="remove"
@refresh="refresh"
@contextmenu="onContextmenu"
/>
<div :class="['tabs-view-content', layout, pageWidth]" :style="`margin-top: ${multiPage ? -24 : 0}px`">
<page-toggle-transition :disabled="animate.disabled" :animate="animate.name" :direction="animate.direction">
<a-keep-alive v-if="multiPage" v-model="clearCaches">
<router-view ref="tabContent" :key="$route.fullPath" />
<router-view v-if="!refreshing" ref="tabContent" :key="$route.fullPath" />
</a-keep-alive>
<router-view v-else />
</page-toggle-transition>
@ -38,7 +39,8 @@ export default {
clearCaches: [],
pageList: [],
activePage: '',
menuVisible: false
menuVisible: false,
refreshing: false
}
},
computed: {
@ -47,7 +49,8 @@ export default {
return [
{ key: '1', icon: 'vertical-right', text: this.$t('closeLeft') },
{ key: '2', icon: 'vertical-left', text: this.$t('closeRight') },
{ key: '3', icon: 'close', text: this.$t('closeOthers') }
{ key: '3', icon: 'close', text: this.$t('closeOthers') },
{ key: '4', icon: 'sync', text: this.$t('refresh') },
]
},
tabsOffset() {
@ -106,9 +109,6 @@ export default {
this.activePage = key
this.$router.push(key)
},
editPage (key, action) {
this[action](key) // remove
},
remove (key, next) {
if (this.pageList.length === 1) {
return this.$message.warning(this.$t('warn'))
@ -124,19 +124,30 @@ export default {
this.$router.push(this.activePage)
}
},
onContextmenu (e) {
const pageKey = getPageKey(e.target)
refresh (key, page) {
page = page || this.pageList.find(item => item.fullPath === key)
page.loading = true
this.clearCache(page)
if (key === this.activePage) {
this.reloadContent(() => page.loading = false)
} else {
// loading
setTimeout(() => page.loading = false, 500)
}
},
onContextmenu(pageKey, e) {
if (pageKey) {
e.preventDefault()
e.meta = pageKey
this.menuVisible = true
}
},
onMenuSelect (key, target) {
let pageKey = getPageKey(target)
onMenuSelect (key, target, pageKey) {
switch (key) {
case '1': this.closeLeft(pageKey); break
case '2': this.closeRight(pageKey); break
case '3': this.closeOthers(pageKey); break
case '4': this.refresh(pageKey); break
default: break
}
},
@ -172,6 +183,22 @@ export default {
this.$router.push(this.activePage)
}
},
clearCache(page) {
page._init_ = false
this.clearCaches = [page.cachedKey]
},
reloadContent(onLoaded) {
this.refreshing = true
setTimeout(() => {
this.refreshing = false
this.$nextTick(() => {
this.setCachedKey(this.$route)
if (typeof onLoaded === 'function') {
onLoaded.apply(this, [])
}
})
}, 200)
},
pageName(page) {
return this.$t(getI18nKey(page.keyPath))
},
@ -180,6 +207,7 @@ export default {
*/
addListener() {
window.addEventListener('page:close', this.closePageListener)
window.addEventListener('page:refresh', this.refreshPageListener)
window.addEventListener('unload', this.unloadListener)
},
/**
@ -187,6 +215,7 @@ export default {
*/
removeListener() {
window.removeEventListener('page:close', this.closePageListener)
window.removeEventListener('page:refresh', this.refreshPageListener)
window.removeEventListener('unload', this.unloadListener)
},
/**
@ -198,6 +227,14 @@ export default {
const closePath = typeof closeRoute === 'string' ? closeRoute : closeRoute.path
this.remove(closePath, nextRoute)
},
/**
* 页面刷新事件监听
* @param event 页签关闭事件
*/
refreshPageListener(event) {
const {pageKey} = event.detail
this.refresh(pageKey)
},
/**
* 页面 unload 事件监听器添加页签到 session 缓存用于刷新时保留页签
*/
@ -206,7 +243,7 @@ export default {
sessionStorage.setItem(process.env.VUE_APP_TBAS_KEY, JSON.stringify(tabs))
},
createPage(route) {
return {keyPath: route.matched[route.matched.length - 1].path, fullPath: route.fullPath}
return {keyPath: route.matched[route.matched.length - 1].path, fullPath: route.fullPath, loading: false}
},
/**
* 设置页面缓存的key
@ -240,20 +277,6 @@ export default {
...mapMutations('setting', ['correctPageMinHeight'])
}
}
/**
* 由于ant-design-vue组件库的TabPane组件暂不支持自定义监听器无法直接获取到右键target所在标签页的 pagekey 故增加此方法用于
* 查询右键target所在标签页的标识 pagekey 以用于自定义右键菜单的事件处理
* TabPane组件支持自定义监听器后可去除该方法并重构 自定义右键菜单的事件处理
* @param target 查询开始目标
* @param depth 查询层级深度 查找层级最多不超过3层超过3层深度直接返回 null
* @returns {String}
*/
function getPageKey (target, depth = 0) {
if (depth > 2 || !target) {
return null
}
return target.getAttribute('pagekey') || getPageKey(target.firstElementChild, ++depth)
}
</script>
<style scoped lang="less">

View File

@ -4,18 +4,21 @@ module.exports = {
closeLeft: '关闭左侧',
closeRight: '关闭右侧',
closeOthers: '关闭其它',
refresh: '刷新页面',
warn: '这是最后一页,不能再关闭了',
},
HK: {
closeLeft: '關閉左側',
closeRight: '關閉右側',
closeOthers: '關閉其它',
refresh: '刷新頁面',
warn: '這是最後一頁,不能再關閉了',
},
US: {
closeLeft: 'close left',
closeRight: 'close right',
closeOthers: 'close others',
refresh: 'refresh the page',
warn: 'This is the last page, you can\'t close it',
},
}

View File

@ -5,6 +5,10 @@ const TabsPagePlugin = {
$closePage(closeRoute, nextRoute) {
const event = new CustomEvent('page:close', {detail:{closeRoute, nextRoute}})
window.dispatchEvent(event)
},
$refreshPage(pageKey) {
const event = new CustomEvent('page:refresh', {detail:{pageKey}})
window.dispatchEvent(event)
}
}
})