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>