自学内容网 自学内容网

vue3 ts admin动态tab

<template>
  <div class="admin">
    <el-container class="auto-height">
      <el-container>
        <el-aside style="width: auto">
          <el-menu
            class="menu-left"
            :router="true"
            :default-active="defaultActive"
            :collapse="isCollapse"
            @open="handleOpen"
            @close="handleClose"
            @select="handleSelect"
          >
            <MenuTree :model="treeData"></MenuTree>
          </el-menu>
        </el-aside>
        <el-container class="flex-view">
          <el-header class="navbar">
            <el-row>
              <el-col :span="4">
                <el-row>
                  <el-col :span="2">
                    <NavCollapse @handleCollapse="handleCollapse"> </NavCollapse>
                  </el-col>
                  <el-col :span="22">
                    <NavBreadcrumb> </NavBreadcrumb>
                  </el-col>
                </el-row>
              </el-col>
              <el-col :span="20">
                <el-menu
                  mode="horizontal"
                  :ellipsis="false"
                  class="menu-top"
                  :router="true"
                  :default-active="defaultActive"
                >
                  <MenuTree :model="treeData"></MenuTree>
                </el-menu>
              </el-col>
            </el-row>
          </el-header>
          <el-main>
            <el-tabs
              class="admin-tab"
              v-model="editableTabsValue"
              type="card"
              closable
              @tab-change="changeTab"
              @tab-remove="removeTab"
            >
              <el-tab-pane
                v-for="item in editableTabs"
                :key="item.name"
                :label="item.title"
                :name="item.name"
              >
                <router-view v-slot="{ Component }">
                  <transition name="fade">
                    <component :is="Component" />
                  </transition>
                </router-view>
              </el-tab-pane>
            </el-tabs>
          </el-main>
          <el-footer>Footer</el-footer>
        </el-container>
      </el-container>
    </el-container>
    <el-backtop :right="100" :bottom="100" />
  </div>
</template>
<style lang="css">
.admin {
  margin: 0;
  padding: 0;
}
.auto-height {
  height: calc(100vh - 15px);
}
.el-menu--horizontal > .el-menu-item:nth-child(1) {
  margin-right: auto;
}
.el-menu--horizontal.el-menu {
  border-bottom: none;
}
.el-main {
  margin-top: 0;
  padding: 0;
}
.navbar {
  line-height: 60px;
  overflow: hidden;
  box-shadow: 0 1px 4px rgba(0, 21, 41, 0.08);
}
.menu-left {
  height: 100%;
}
.admin-tab {
  height: 100%;
}
.admin-tab > .el-tabs__header {
  margin: 0;
  height: 30px;
  box-shadow: 0 1px 4px rgba(0, 21, 41, 0.08);
}
.admin-tab > .el-tabs__content {
  height: 100%;
}
.el-tab-pane {
  height: 100%;
}
.flex-view {
  flex-grow: 1;
}
</style>
<script setup lang="ts">
import { ref, watch } from 'vue'
import { useRoute, useRouter } from 'vue-router'
import NavCollapse from '@/components/admin/NavCollapse.vue'
import NavBreadcrumb from '@/components/admin/NavBreadcrumb.vue'
import MenuTree from '@/components/admin/MenuTree.vue'
const route = useRoute()
const router = useRouter()
const defaultActive = ref(route.path)
const isCollapse = ref(true)
const handleCollapse = () => {
  isCollapse.value = !isCollapse.value
}
// eslint-disable-next-line @typescript-eslint/no-unused-vars
const handleOpen = (key: string, keyPath: string[]) => {}
// eslint-disable-next-line @typescript-eslint/no-unused-vars
const handleClose = (key: string, keyPath: string[]) => {}
// eslint-disable-next-line @typescript-eslint/no-unused-vars
const handleSelect = (key: string, keyPath: string[]) => {}

const editableTabsValue = ref(route.path)
const editableTabs = ref([
  {
    title: route.meta.title + '',
    name: route.path,
  },
])
// 切换tab时切换路由
const changeTab = (targetName: string) => {
  router.push(targetName)
}
// 删除时不删除当前的
const removeTab = (targetName: string) => {
  const tabs = editableTabs.value
  let activeName = editableTabsValue.value
  if (activeName === targetName) {
    return
  }
  if (activeName === targetName) {
    tabs.forEach((tab, index) => {
      if (tab.name === targetName) {
        const nextTab = tabs[index + 1] || tabs[index - 1]
        if (nextTab) {
          activeName = nextTab.name
        }
      }
    })
  }

  editableTabsValue.value = activeName
  editableTabs.value = tabs.filter((tab) => tab.name !== targetName)
}
// 路由改变自动切换tab
watch(
  () => route.path,
  // eslint-disable-next-line @typescript-eslint/no-unused-vars
  (newPath, oldPath) => {
    editableTabsValue.value = newPath
    const x = editableTabs.value.filter((tab) => tab.name == newPath)
    if (x.length === 0) {
      editableTabs.value.push({
        title: route.meta.title + '',
        name: route.path,
      })
    }
  },
)

const treeData = ref([
  {
    index: '/admin',
    title: '后台管理',
    icon: 'location',
    children: [
      {
        index: '/admin/system',
        title: '系统管理',
        icon: 'location',
        children: [
          {
            index: '/admin/system/user',
            title: '用户管理',
            icon: 'location',
          },
          {
            index: '/admin/system/role',
            title: '角色管理',
            icon: 'location',
          },
          {
            index: '/admin/system/permission',
            title: '权限管理',
            icon: 'location',
          },
          {
            index: '/admin/system/group',
            title: '组织管理',
            icon: 'location',
          },
          {
            index: '/admin/system/menu',
            title: '菜单管理',
            icon: 'location',
          },
        ],
      },
    ],
  },
])
</script>

在这里插入图片描述


原文地址:https://blog.csdn.net/by2233/article/details/144778822

免责声明:本站文章内容转载自网络资源,如本站内容侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!