在这里插入图片描述

思路

  1. 点击左侧菜单,右侧内容展示区显示对应的选项卡
  2. 点击右侧选项卡,左侧菜单也相应的选中。点击tabs跳转到相应的路径,route.push,菜单中用computed监听path的变化
  3. 解决刷新后,tabs数据丢失的问题

因为route可以直接获取到当前路由的path等信息,不用在菜单中点击菜单的触发方法,直接获取当前的路由,然后菜单页面和tabs页面都用computed监听path的变化

tabs选项卡存储在store里面

因为菜单组件和tab标签页组建共享tabs数组,所以存储在store里面
首先创建tabs标签的接口:

// 选项卡的数据类型, 规定数据类型就只能有title 和 path
export interface ITabe{
  title:string,
  path:string
}

在store里面

export interface State {
  count: number,
  collapse: boolean,
  tabsList: Array<ITabe>
}

export const key: InjectionKey<Store<State>> = Symbol()

export const store = createStore<State>({
  state: {
    tabsList: []
  },
  mutations: {
    addTabe(state: State, tab: ITabe) {
      // 判断是否已经存在,如果不存在,才放入
      if(state.tabsList.some(item => item.path === tab.path)) return;
      state.tabsList.push(tab)
    }
  },
  getters: {
    // 获取Tabs
    getTabs(state: State) {
      return state.tabsList
    }
  }
})

tabs页面

获取tabs数据

const tabsList = computed(() => {
  return store.getters['getTabs']
})

添加选项卡(每点击菜单,就添加一个)

const addTab = () => {
  const { path, meta } = route
  const tab: ITabe = {
    path: path,
    title: meta.title as string
  }
  store.commit('addTabe', tab)
}

点击选项卡

const clickBtn = (tab: any) => {
  const { props } = tab
  //跳转路由
  router.push({ path: props.name })
}

当前激活的选项卡(当前所在的路由)

const activeTab = ref('2') //是v-model的绑定
const setActiveTab = () => {
  activeTab.value = route.path
}

删除选项卡

//删除选项卡,跳转到临近页面,这个tabs标签删除
const removeTab = (targetName: string) => {
  if(store.state.tabsList.length === 1) return
  const tabs = tabsList.value
  let activeName = activeTab.value
  if (activeName === targetName) {   //如果当前的路由是要删除的页面
    tabs.forEach((tab:ITabe, index:number) => {
      if (tab.path === targetName) {
        const nextTab = tabs[index + 1] || tabs[index - 1]  //如果在中间的tab,删除会选择在后面的一个;如果在最后,会选择在前面的一个tab
        if (nextTab) {
          activeName = nextTab.path  //更换当前路由的地址
        }
      }
    })
  }
  //重新设置当前激活的选项卡
  activeTab.value = activeName
  //重新设置选项卡数据,将数组中去掉删除的元素
  store.state.tabsList = tabs.filter((tab:ITabe) => tab.path !== targetName)
  //跳转路由
  router.push({path: activeName})
}

解决刷新数据丢失的问题

const beforeRefresh = () => {
  window.addEventListener("beforeunload",() => { //监听刷新
     // sessionStorage当浏览器关闭时,结束。localStorage,没有期限
     sessionStorage.setItem('tabsView',JSON.stringify(tabsList.value))
  })
  //页面加载时取数据
  let tabSession = sessionStorage.getItem('tabsView')
  if(tabSession) {
    let oldTabs = JSON.parse(tabSession)
    if(oldTabs.length > 0) {
      store.state.tabsList = oldTabs
    }
  }
}

完整代码

<template>
  <el-tabs
    v-model="activeTab"
    @tab-click = "clickBtn"
    type="card"
    class="demo-tabs"
    closable	
    @tab-remove="removeTab"
  >
    <el-tab-pane
      v-for="item in tabsList"
      :key="item.path"
      :label="item.title"
      :name="item.path"
    >
    </el-tab-pane>
  </el-tabs>
</template>
<script lang="ts" setup>
import { onMounted, ref,watch,computed } from 'vue'
import { useStore } from '@/store';
import { useRoute, useRouter } from 'vue-router'; 
import { ITabe } from '@/store/type';
const store = useStore()
const route = useRoute()
const router = useRouter()
//获取tabs数据
const tabsList = computed(() => {
    return store.getters['getTabs']
})
console.log(tabsList,"tabsList")
// let tabIndex = 2
const activeTab = ref('2')

//点击选项卡,跳转到相应的页面,菜单也恢复到相应的页面
const clickBtn = (tab:any) => {
    const { props } = tab
    router.push({path: props.name})
}

//删除选项卡,跳转到临近页面,这个tabs标签删除
const removeTab = (targetName: string) => {
  if(store.state.tabsList.length === 1) return
  const tabs = tabsList.value
  let activeName = activeTab.value
  if (activeName === targetName) {   //如果当前的路由是要删除的页面
    tabs.forEach((tab:ITabe, index:number) => {
      if (tab.path === targetName) {
        const nextTab = tabs[index + 1] || tabs[index - 1]  //如果在中间的tab,删除会选择在后面的一个;如果在最后,会选择在前面的一个tab
        if (nextTab) {
          activeName = nextTab.path  //更换当前路由的地址
        }
      }
    })
  }
  //重新设置当前激活的选项卡
  activeTab.value = activeName
  //重新设置选项卡数据,将数组中去掉删除的元素
  store.state.tabsList = tabs.filter((tab:ITabe) => tab.path !== targetName)
  //跳转路由
  router.push({path: activeName})
}

//添加路由的选项卡
const addTabs = () => {
    const { path,meta } = route
    const tabs:ITabe = {
        title: meta.title as string,
        path: path
    }
    store.commit('addTab',tabs)
}
//激活选项卡
const setActiveTab = () => {
    activeTab.value = route.path  //因为el-tab-pane的name是item.path,所以activeTab也是path
}

watch(() => route.path,()=> {
    //激活选项卡
    setActiveTab()
    //监听路由的变化
    addTabs()
}) 

//解决刷新数据页面丢失的问题
const beforeRefresh = () => {
  window.addEventListener("beforeunload",() => { //监听刷新
     // sessionStorage当浏览器关闭时,结束。localStorage,没有期限
     sessionStorage.setItem('tabsView',JSON.stringify(tabsList.value))
  })
  //页面加载时取数据
  let tabSession = sessionStorage.getItem('tabsView')
  if(tabSession) {
    let oldTabs = JSON.parse(tabSession)
    if(oldTabs.length > 0) {
      store.state.tabsList = oldTabs
    }
  }
}
//调用函数需要在模板加载之后调用
onMounted(() => {
    beforeRefresh()
    setActiveTab()
    addTabs()
})
</script>
<style>
</style>
Logo

前往低代码交流专区

更多推荐