一、动态路由数据结构(mock数据,不限层级)
export default [
{
url: '/api/routerInfo',
method: 'get',
response: () => {
return {
code: 200,
message: 'ok',
data: [
{
path: "/study",
component: 'Layout',
meta: { title: '学习管理'},
name: "Study",
children:[
{
path: "study1",
name: "Study1",
component:'/study/index',
meta: { title: '学习1' },
}
]
},
{
path: "/multiStage",
component: 'Layout',
meta: { title: '多层级'},
name:'MultiStage',
children:[
{
path: "stage1",
name: "One",
component:'/multiStage/index',
meta: { title: '一层-01' },
},
{
path: "stage2",
name: "two",
meta: { title: '一层-02' },
children:[
{
path: "one1",
name: "One-1",
component:'/multiStage/one/index',
meta: { title: '02-1' },
},
{
path: "one2",
name: "One-2",
component:'/multiStage/one/two',
meta: { title: '02-2' }
}
]
}
]
}
]
}
}
},
]
二、静态路由数据
import { createWebHistory, createRouter } from "vue-router";
import Layout from "@/layout/index.vue"
export const routes = [
{
path: "/",
redirect:'/dashboard',
name:'Dashboard',
component: Layout,
meta: { title: '首页' },
children:[
{
path: "dashboard",
name: "Dashboard",
component: () => import('@/pages/dashboard/index.vue'),
meta: { title: '首页1' },
}
]
},
{
path: "/login",
name: "Login",
component: () => import('@/pages/login/index.vue'),
hidden:true
}
];
export const errorRoute = [
{
path: '/:pathMatch(.*)*',
name: '404',
hidden: true,
component: () => import('@/pages/404/index.vue'),
meta: { title: 'P404' }
}
]
const router = createRouter({
history: createWebHistory(),
routes,
});
export default router;
三、登录后调用
import { defineStore } from 'pinia'
import { ref} from 'vue'
import {getUser,getRouterInfo} from '@/api/user.ts'
import {routes,errorRoute} from '@/router'
import {dealAsyncRouter} from '@/utils/dealRouter.ts'
export const useUserInfoStore = defineStore('userInfo', () => {
const userInfo = ref({})
const routerList = ref([])
async function getUserRouterInfoAction() {
const res = await getUser()
userInfo.value = res?.data
await getRouterInfoAction()
}
async function getRouterInfoAction(){
await getRouterInfo().then((res:any)=>{
const asyncRouters = dealAsyncRouter(res.data)
routerList.value = routes.concat(asyncRouters)
}).catch(()=>{
routerList.value = routes
})
routerList.value = routerList.value.concat(errorRoute)
}
return { userInfo,routerList, getUserRouterInfoAction }
})
import Layout from "@/layout/index.vue"
interface RouteObj {
path:string
name:string
redirect?:string
component:any,
meta?:MetaObj
children?: any
hidden?:boolean
}
interface MetaObj {
title:string
icon?:string
}
export const dealAsyncRouter = (data:RouteObj[])=>{
let routers = dealRouter(data)
return routers
}
const dealRouter = (data:RouteObj[])=>{
let routers = data
routers.forEach(item=>{
if(item.component==='Layout'){
item.component = Layout
}else if(item.component){
item.component = dealFilePath(item.component)
}
if(item.children){
item.children = dealRouter(item.children)
}
})
return routers
}
const dealFilePath = (data:string)=>{
return () =>import(`/src/pages${data}.vue`)
}
四、在main.ts注入
import { createApp } from 'vue'
import './styles/index.scss'
import App from './App.vue'
import router from './router/index.js'
import ElementPlus from 'element-plus'
import 'element-plus/dist/index.css'
import 'element-plus/theme-chalk/dark/css-vars.css'
import { createPinia } from 'pinia'
import '@/permission'
const app = createApp(App)
const pinia = createPinia()
app.use(pinia)
app.use(router)
app.use(ElementPlus)
app.mount('#app')
五、App.vue- 视图展示
<template>
<router-view />
</template>
六、permission.ts- 路由拦截
import router from './router'
import {useUserInfoStore} from '@/stores/userInfo.ts'
import {isEmpty} from 'lodash'
import NProgress from 'nprogress'
import 'nprogress/nprogress.css'
router.beforeEach(async (to:any, from:any, next:any) => {
NProgress.start()
const store = useUserInfoStore()
const token = localStorage.getItem('token')
if(token){
if(to.path==='/login'){
next({path:'/'})
}else{
if(isEmpty(store.userInfo)){
await store.getUserRouterInfoAction()
if(!isEmpty(store.routerList)){
store.routerList.forEach((item:any)=>{
router.addRoute(item)
})
next({...to, replace: true})
}
}
next()
}
}else{
if(to.path==='/login'){
next()
}else{
next({path:'/login'})
}
}
})
router.afterEach(()=>{
NProgress.done()
})
备注:可疯狂吐槽(咸鱼不不翻身)