router/index.ts
import{createRouter,createWebHistory,RouteRecordRaw} from 'vue-router';
import {getToken,getRouters} from "@/store/cache";
import store from "@/store/store";
let moduleView = import.meta.globEager('../views/**/**.vue');
let layoutView = import.meta.globEager('../views/**.vue');
//配置一些公共路由
const routes:Array<RouteRecordRaw>=[
{
path:'/login',
name:'login',
component: () => moduleView['../views/login/index.vue'],
meta:{
title:'用户登录'
}
},{
path:'/',
name:'layout',
redirect: '/product',
component: () => layoutView['../views/home.vue'],
children: []
},{
path:'/404',
name:'404',
component: () => layoutView['../views/404.vue'],
meta:{
title:'404'
}
}
]
const router = createRouter({
history:createWebHistory(),
routes
})
//模拟后台返回路由数据 为了方便查看就写在一个文件里
let routerList = [{
name:'home',
path:'/home',
mate:{
title:'首页',
}
},{
name:'product',
path:'/product',
mate:{
title:'产品列表',
}
},{
name:'news',
path:'/news',
mate:{
title:'新闻列表',
}
}]
router.beforeEach((to,from,next)=>{//beforeEach是router的钩子函数,在进入路由前执行
const isLoadRouters = store.state.asyncRoutesMark
let token = getToken();
let routers;
//这是我实际中的动态路由数据 现在使用routerList
//if(getRouters() && getRouters() != 'undefined' ){
// routers = JSON.parse(getRouters());
//}
// 有token routers
if (to.path == '/login') {
next()
} else {
//用户已登录
if (token && JSON.stringify(routerList) != '[]' ) {
if (isLoadRouters) {
console.log('路由已添加,直接跳转到目标页面')
next()
} else {
//解决刷新页面空白
console.log('重新加载路由,并跳转到目标页')
store.commit('setRouters', routers)
store.commit('setAsyncRoutesMark', true)
//添加路由 在layout中添加子路由
const layout:any = routes.find((item) => item.name == 'layout')!;
routerList.forEach((item:any )=> {
layout.children.push({
path: item.path,
name: item.name,
component: () => moduleView[`../views${item.path}/index.vue`],
meta: {
title: item.meta.title,
},
})
})
//这个要在动态中配置 不然会出现空白页的情况
layout.children.push({
path: '/:pathMatch(.*)',
redirect: '/404',
component: () => moduleView[`../views${404}.vue`],
meta: {
title: '404',
},
})
router.addRoute(layout)
next({ ...to, replace: true })
}
} else {
console.log('无登录信息,跳转到登录页');
store.commit('setAsyncRoutesMark', false)
next(`/login`)
}
}
})
export default router
store/index.ts (使用全局变量来控制动态路由是否需要添加)
import {createStore} from "vuex";
import persistedState from 'vuex-persistedstate'
export default createStore({
state:{
asyncRoutesMark: false,
},
mutations: {
setAsyncRoutesMark(state, data) {
state.asyncRoutesMark = data
},
},
plugins: [persistedState()]
})
在main.ts中引入
import { createApp} from 'vue'
import App from './App.vue'
import router from './router/index'
const app = createApp(App)
const setupAll = async () => {
app.use(router).mount('#app')
}
setupAll()
最后一个重点
写在App.vue里 (因为页面刷新之后动态路由会丢失 所以必须初始化控制动态路由是否需要添加的变量)
window.addEventListener('beforeunload', e => beforeunloadFn(e))
const beforeunloadFn = (()=> {
store.commit('setAsyncRoutesMark',false)
})