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) })
复制