web前端

vue3嵌套路由(后台管理系统)

2022-11-07  本文已影响0人  姜治宇

如何设计一个后台管理系统的路由呢?这里就需要使用到嵌套路由。

嵌套路由

带children的嵌套路由可以有页面,也可以没有。这里带页面的是home页,因为要设计后台框架结构,没有的话就会指向默认页面,参考任务管理这一项。
router.ts:

import { createRouter, createWebHistory,  RouterView } from "vue-router"
const routes = [
  {
    path: "/login",
    name: "login",
    meta: {
      title: "登录"
    },
    component: () => import("@/pages/login/index.vue")
  },
  {
    path: "/",
    name: "index",
    meta: {
      title: "首页"
    },
    component: () => import("@/pages/home/index.vue"),//页面实现后台结构
    children: [ //子路由
      {
        path: "",
        redirect: "terrain_slice"
      },
      {
        path: "terrain_slice",
        name: "terrain_slice",
        meta: {
          title: "地形切片"
        },
        component: () => import("@/pages/TerrainSlice/index.vue")
      },
      {
        path: "image_slice",
        name: "image_slice",
        meta: {
          title: "影像切片"
        },
        component: () => import("@/pages/ImageSlice/index.vue")
      },
      {
        path: "task_manage",
        name: "task",
        meta: {
          title: "任务管理"
        },
        component: RouterView, //无页面
        children: [ //子路由
          {
            path: "",
            name: "task_manage",
            meta: {
              title: "任务管理"
            },
            component: () => import("@/pages/TaskManage/index.vue")
          },
          {
            path: "task_details",
            name: "task_details",
            meta: {
              title: "任务详情"
            },
            component: () => import("@/pages/TaskManage/TaskDetails/index.vue")
          }
        ]
      }
    ]
  }
]


const ssoResult = () => {
  return new Promise((resolve) => {
    setTimeout(()=>{
        resolve({accessToken:'123456'})
    },200)
  })
}

const router = createRouter({
  routes,
  history: createWebHistory()
})
router.beforeEach(async (to, from, next) => {
  console.log(to.path)
  if (to.path.indexOf("login") === -1) { //如果是访问首页,需要检测token
   
    const token = localStorage.getItem("token")

    if (token) {
      next()
    } else {
      let result: any = await ssoResult() //异步获取token

      if (result && result.accessToken) {
        localStorage.setItem("token", result.accessToken)
        next()
      } else {
        next("/login")
      }
    }
  } else {
    next()
  }
})
export default router

App.vue:

<template>
  <el-config-provider :locale="locale">
    <div class="app">
      <RouterView />
    </div>
  </el-config-provider>
</template>

<script setup lang="ts">
import zhCn from "element-plus/lib/locale/lang/zh-cn"
import { RouterView } from "vue-router"
const locale = zhCn
</script>

main.js:

import { createApp } from "vue"
import microApp from "@micro-zoe/micro-app"
import "virtual:svg-icons-register"
import router from "@/router"
import store from "@/store"
import SvgIcon from "@/components/SvgIcon/index.vue"
import App from "./App.vue"
import "@/styles/index.scss"
import handleRouterPermission from "@/utils/permission"

microApp.start()

const app = createApp(App)
app.use(router)
app.use(store)
app.component("SvgIcon", SvgIcon)

// 处理权限登录逻辑
handleRouterPermission(router)

app.mount("#app")

home/index.vue

<template>
    <el-config-provider :locale="locale">
      <div class="content">
        <Header /><!--顶部-->
        <div class="app-content">
          <Sidebar /> <!--侧边栏-->
          <div class="app-container">
            <RouterView /> <!--主体部分-->
          </div>
        </div>
      </div>
    </el-config-provider>
  </template>
  
  <script setup lang="ts">
  import zhCn from "element-plus/lib/locale/lang/zh-cn"
  import { RouterView } from "vue-router"
  import Header from "@/components/Header/index.vue"
  import Sidebar from "@/components/Sidebar/index.vue"
  const locale = zhCn
  </script>
  
  <style lang="scss" scoped>
  </style>

侧边栏sidebar.vue:

<template>
  <div class="sidebar">
    <router-link class="siderbar-item" v-for="p in menuList" :key="p.path" :to="{ name: p.path }">
      <span class="sidervar-item-title">
        {{ p.name }}
      </span>
    </router-link>
  </div>
</template>

<script setup lang="ts">
import { RouterLink } from "vue-router"
const menuList = [
  {
    name: "地形切片",
    path: "terrain_slice",
    icon: "icon-dx"
  },
  {
    name: "影像切片",
    path: "image_slice",
    icon: "icon-yx"
  },
  {
    name: "任务管理",
    path: "task_manage",
    icon: "icon-rwgl"
  }]
</script>

动态组件

动态组件就是根据参数的不同,显示不同的组件。比如任务管理是一个列表页,而列表项对应的详情页面都不同,这样可以设计一个统一的detail页面,再根据参数的不同显示不同组件的信息。
detail/index.vue:

<template>
  <div class="common-container no-scrollbar">
    <component :is="chooseComponent"  />
  </div>
</template>
<script setup lang="ts">
import { useRoute } from "vue-router"
import { onMounted, onBeforeUnmount, reactive, ref, computed } from "vue"
import { ElMessage } from "element-plus"
import ImageDetails from "./ImageDetails/index.vue"
import TerrainDetails from "./TerrainDetails/index.vue"
import PointCloudSliceDetails from "./PointCloudSlice/index.vue"
const route = useRoute()
const tasktype = ref<number>(Number(route.query.tasktype)) //接收动态参数
const chooseComponent = computed<any>(() => {  //计算属性,决定显示哪个组件
 
  switch (tasktype.value) {
    case 1:
      return TerrainDetails
    case 2:
      return ImageDetails
    case 3:
      return PointCloudSliceDetails
    case 4:
      return InstanceModelSliceDetails
    case 5:
      return TiltModelSliceDetails
    case 6:
      return GeneralModelSliceDetails

  }
})
</script>
上一篇下一篇

猜你喜欢

热点阅读