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>
⚠️ **GitHub.com Fallback** ⚠️