类似于浏览器窗口一样的路由切换逻辑,看着还是挺高大上的,本以为有很多高级的玩意儿,奈何复杂的东西总是由简单的东西拼接而成的,这个功能也不例外。
本篇文章主要描述两个问题:
如何实现这种Tab标签页的路由效果 如何为路由切换添加转场动画。
该功能的开发主要使用到 AntDesignVue 组件库的Tab组件和 Animate.css
效果如下:
Tab标签页实现
首先是该组件的模板部分, ContextMenu 组件是我们自定义的右键菜单,后面会说到。 a-tabs 组件则是 ant 的组件,具体用法不详述,可以查看官方文档。还有一个 PageToggleTransition 组件,是我们用来实现动画切换的组件,非常简单。
/**
* TabLayout.vue 的模板部分,简单看一下有个印象
*/
:list="menuItems"
:visible.sync="menuVisible"
@select="onMenuSelect"
/>
type="editable-card"
:hide-add="true"
:active-key="activePage"
@change="changePage"
@edit="editPage"
@contextmenu="onContextmenu"
>
{ { page.name }}
原理
维护一个 pageList ,通过监听路由变化动态的添加和删除page。而所谓的page,就是页面的路由对象($route),我们正是通过 $route.fullPath 作为页面的唯一标识的。而删除页面时不光要操作 pageList ,还要利用 keep-alive 组件的 exclude 属性删除缓存。至于 a-tabs 组件的这个插槽,主要是为了绑定一个数据key,以便触发contextmenu事件时,可以更容易的获取到对应页面的key值(fullPath)
理论存在,实践开始。
路由监听
watch: {
$route: {
handler (route) {
this.activePage = route.fullPath
this.putCache(route)
const index = this.pageList.findIndex(item => item.fullPath === route.fullPath)
if (index === -1) {
this.pageList.push(route)
}
},
immediate: true
}
}
路由变化时,主要做三件事:
设置当前页(activePage)
将当前页加入缓存,即移出垃圾桶(dustbin)
如果当前页不在pageList中,则添加进来。
页面跳转
methods: {
changePage (key) {
this.activePage = key
this.$router.push(key)
},
editPage (key, action) {
if (action === 'remove') {
this.remove(key)
}
},
remove (key) {
if (this.pageList.length <= 1) {
return message.info('最后一页了哦~')
}
let curIndex = this.pageList.findIndex(item => item.fullPath === key)
const { matched } = this.pageList[curIndex]
const componentName = last(matched).components.default.name
this.dustbin.push(componentName)
this.pageList.splice(curIndex, 1)
// 如果删除的是当前页才需要跳转
if (key === this.activePage) {
// 判断向左跳还是向右跳
curIndex = curIndex >= this.pageList.length ? this.pageList.length - 1 : curIndex
const page = this.pageList[curIndex]
this.$router.push(page.fullPath).finally(() => {
this.dustbin.splice(0) // 重置,否则会影响到某些组件的缓存
})
}
}
...
...
}
这里主要主要说一下