56 多页签路由数据管理 - udo-bit/naive_admin_pro GitHub Wiki
完成多页签路由数据存储部分的功能开发
这节课我们就需要对多页签的路由数据进行管理,也就是我们需要通过组合式api的方式进行管理。
上节课我们创建了multi-tab-state.ts的文件。
那么我们还是在这里进行数据管理。
export const useMultiTab = () => {
// 获取数据状态信息
const state = useMultiTabInject()
const router = useRouter()
const route = useRoute()
const tabList = computed(() => state.tabList)
const current = computed(() => state.current)
const { message } = useGlobalConfig()
const addTab = (route: RouteLocationNormalized): TabItem => {
// 首先需要区分一下路由信息,如果当前传进来的路由信息是白名单的路由,那么我们不需要进行处理
const item: TabItem = {
route: omit(route, 'matched'),
path: route.path,
tabTitle: route.meta.title,
}
// 需要对不需要的路由进行过滤
if (hasLoginAllowRoutes.includes(route.path))
return item
// 判断当前路由是否已经在菜单中存在
const tabIndex = state.tabList.findIndex(tab => tab.path === route.path)
if (tabIndex !== -1) {
message?.info('当前页面已经打开')
return state.tabList[tabIndex]
}
// 如果不存在,就添加到菜单中
state.tabList.push(item)
return item
}
// 监听路由发生的变化
watch(() => route.fullPath, () => {
state.current = route.path
const index = state.tabList.findIndex(item => item.path === route.path)
// 为了防止路由信息发生变化,我们再重新存储一下路由信息
if (state.tabList[index]) { state.tabList[index].route = omit(route, 'matched') }
else {
// 如果tab不存在的情况,我们就需要添加tab
addTab(route)
}
}, {
immediate: true,
})
return {
tabList,
current,
addTab,
}
}
接下来我们在multi-tab的文件中进行引入调整代码。
<script lang="ts" setup>
import { MoreOutlined } from '@vicons/antd'
import type { DropdownOption } from 'naive-ui'
import TabItemComp from './tab-item.vue'
import type { TabItem } from '~/layouts/multi-tab/type'
const { current, tabList, closeTab, refresh } = useMultiTab()
const router = useRouter()
function renderTab(item: TabItem) {
return h(TabItemComp, { item })
}
function handleChange(path: string) {
router.push(path)
}
function handleClose(path: string) {
// TODO
}
</script>
<template>
<n-tabs
:value="current"
type="card"
class="pt-6px bg-white dark:bg-transparent"
tab-style="min-width: 80px;"
@update:value="handleChange"
@close="handleClose"
>
<template #prefix>
<div class="pl-12px" />
</template>
<template #suffix>
<div class="pr-16px">
</div>
</template>
<n-tab-pane
v-for="tabItem in tabList"
:key="tabItem.path"
closable
:tab="renderTab(tabItem)"
:name="tabItem.path"
/>
</n-tabs>
</template>
最后我们看调整之后的效果。
这一块儿我们创建一个tab-item.vue的文件
然后我们处理一下title和多语言的问题。
<script lang="ts" setup>
import type { TabItem } from './type'
defineProps<{
item: TabItem
}>()
const { current } = useMultiTab()
</script>
<template>
<span @contextmenu="onContextmenu">
{{ $t(item.tabTitle) }}
</span>
</template>