Vue3 Element-Plus Tabs标签页与路由 动态标签页

封装为一个组件

<template>
  <div class="TagPage">
    <el-tabs type="border-card"
      v-model="activeTab" :closable="editableTabs.length > 1"
      @tab-click="handleTabClick"
      @tab-remove="handleTabRemove">
      <el-tab-pane v-for="tab in editableTabs" :key="tab.name"
        :label="tab.title" :name="tab.name">
      </el-tab-pane>
    </el-tabs>
  </div>
</template>

<script setup>
import { ref, watch } from 'vue'
// 路由
import { useRoute, useRouter } from 'vue-router'
// pinia
import { useTagStore } from '@/stores/modules/tag.js'
const store = useTagStore()
const route = useRoute()
const router = useRouter()
// 展示的标签页 v-model绑定的值
const activeTab = ref('')
// 可选标签页
const editableTabs = ref([])
// 第一次打开网页初始化pinia中存储的标签页
if (window.performance.navigation.type !== 1) store.addTag([])

// 选中标签页的事件 (路由跳转到选中的标签页)
const handleTabClick = (tab) => {
  router.push(tab.props.name)
}

// 删除标签页
const handleTabRemove = (targetName) => {
   // filter循环找到未删除的标签页重新赋值给可选标签页
  editableTabs.value = editableTabs.value.filter(
    (tab) => tab.name !== targetName
  )
  // 获取最后一个标签并跳转到最后一个标签页并给展示的标签页赋值
  const lastTab = editableTabs.value[editableTabs.value.length - 1]
  activeTab.value = lastTab ? lastTab.name : ''
  router.push(activeTab.value)
  // 同时删除pinia中存储的标签页
  store.delTag(targetName)
}
// 通过watch监听来获得用户点击过的标签页
watch(() => route,(newVal) => {
    // 先访问pinia中是否存储的有标签页信息(有则展示,无则将可选标签页赋值为空数组)
    editableTabs.value = store.tagList.length ? store.tagList : []
    // 判断路由跳转的页面是否已在可选标签页数据中
    const isNewTab = !editableTabs.value.some((tab) => tab.name === newVal.path)
    // 如果不在进行以下操作
    if (isNewTab) {
    /* 这里我是给标签页的长度做出了限制,最多有六个标签页,如果超出六个标签页
    则删除第一个标签页,若第一个标签页是选中状态,则删除第二个。 */
      if (editableTabs.value.length > 5) {
        const indexToRemove = activeTab.value !== newVal.path ? 1 : 0
        editableTabs.value.splice(indexToRemove, 1)
      }
      // 将标签页存储到可选择标签页中并存储到pinia中
      editableTabs.value.push({
        name: newVal.path,
        title: newVal.meta.title,
        content: newVal.meta.title
      })
      store.addTag(editableTabs.value)
    }
    activeTab.value = newVal.path
  },{ deep: true, immediate: true })
</script>

<style scoped lang="scss">
.TagPage {
  width: 100%;
  height: 40px;
  margin-bottom: 13px;
  overflow: hidden;
}

:deep(.el-tabs__content) {
  padding: 0;
  height: 0;
}
</style>

为什么要存到pinia: 

        pinia做了数据持久化处理,存到pinia是为了防止刷新标签页丢失,也可以通过localStorage存到本地。

总结:
        综合思路:通过watch监听路由变化然后将监听到的路由保存起来通过增删来实现标签页的切换。

有问题或疑惑请留言或者私信邮箱:zh_brave@163.com

  • 3
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Vue 3和Element Plus提供了一种简单的方法来实现侧边菜单栏与标签之间的联动。下面是一个基本示例,演示了如何实现这一功能: 1. 首先,确保你已经安装了Vue 3和Element Plus,并在项目中引入它们。 2. 创建一个侧边菜单栏组件(SideMenu),用于展示菜单项。这个组件可以使用Element Plus的Menu组件来创建。 ```html <template> <el-menu :default-active="activeMenu" @select="handleMenuSelect"> <el-menu-item v-for="item in menuItems" :key="item.path" :index="item.path"> {{ item.name }} </el-menu-item> </el-menu> </template> <script> export default { data() { return { activeMenu: '', // 当前选中的菜单项 menuItems: [ { name: '菜单1', path: '/menu1' }, { name: '菜单2', path: '/menu2' }, // 其他菜单项... ] } }, methods: { handleMenuSelect(index) { this.activeMenu = index; // 更新选中的菜单项 this.$router.push(index); // 导航到对应的路由 } } } </script> ``` 3. 创建一个标签组件(Tabs),用于展示已打开的面。这个组件可以使用Element Plus的Tabs组件来创建。 ```html <template> <el-tabs v-model="activeTab" type="border-card" @tab-remove="handleTabRemove"> <el-tab-pane v-for="tab in openedTabs" :key="tab.path" :label="tab.name" :name="tab.path"> <!-- 面内容 --> </el-tab-pane> </el-tabs> </template> <script> export default { data() { return { activeTab: '', // 当前选中的标签 openedTabs: [] // 已打开的标签 } }, methods: { addTab(tab) { const index = this.openedTabs.findIndex(item => item.path === tab.path); if (index === -1) { this.openedTabs.push(tab); } this.activeTab = tab.path; // 选中新打开的标签 }, removeTab(targetName) { const index = this.openedTabs.findIndex(item => item.path === targetName); if (index !== -1) { this.openedTabs.splice(index, 1); } }, handleTabRemove(targetName) { this.removeTab(targetName); if (targetName === this.activeTab) { this.activeTab = this.openedTabs[this.openedTabs.length - 1].path; } } } } </script> ``` 4. 在你的主面中,使用以上两个组件来实现联动效果。 ```html <template> <div> <side-menu></side-menu> <tabs></tabs> </div> </template> <script> import SideMenu from './SideMenu.vue'; import Tabs from './Tabs.vue'; export default { components: { SideMenu, Tabs } } </script> ``` 在这个例子中,当你点击侧边菜单栏的菜单项时,会更新选中的菜单项,并导航到对应的路由。同时,会在标签中打开一个新的标签。如果你点击已打开的标签的关闭按钮,会关闭该标签并自动选中最后一个打开的标签。 这样就实现了侧边菜单栏与标签的联动效果。你可以根据自己的需求进行定制和扩展。希望对你有所帮助!

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值