vue3+vite动态加载路由,本地路由和线上路由匹配方式
作者:arno-cai
这篇文章主要介绍了vue3+vite动态加载路由,本地路由和线上路由匹配方式,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
使用场景
本地全路由动态匹配线上路由
目的
本地路由方便开发配置,匹配线上路由,进行页面路由控制
内容
// router/constRoutes.js // --------------------------------------- // constRoutes 固定需要加载的路由, // notFound 动态路由加载完成后再添加,否则刷新页面,此时还没有路由,会直接定向到notFound页面 // --------------------------------------- export const constRoutes = [ { path: '/', redirect: '/home' }, { path: '/home', name: 'home', component: () => import('@/views/home/index.vue') }, { path: '/login', name: 'login', component: () => import('@/views/login/index.vue') } ] export const notFound = { path: '/:pathMatch(.*)*', name: 'notFound', component: () => import('@/views/not-found/not-found.vue') }
// router/asyncRoutes.js // --------------------------------------- // 注意:children下的path不需要加'/' // meta下可以加各种本地你想要的参数 // --------------------------------------- const Layout = () => import('@/layout/index.vue') export const asyncRoutes = [ { path: '/monitoringCenter', name: 'MonitoringCenter', component: Layout, meta: { title: '监控中心' }, children: [ { path: 'carMonitoring', name: 'CarMonitoring', meta: { title: '车辆监控' }, children: [ { path: 'positioning', name: 'Positioning', component: () => import('@/views/monitoringCenter/positioning/index.vue'), meta: { title: '实时定位' } } ] }, { path: 'monitorSetting', name: 'MonitorSetting', meta: { title: '监控设置' }, children: [ { path: 'ruleManagement', name: 'RuleManagement', component: () => import('@/views/monitoringCenter/ruleManagement/index.vue'), meta: { title: '报警规则' } } ] } ] },
// router/index.js // --------------------------------------- // 先加载constRoutes 固定路由 // --------------------------------------- import { createRouter, createWebHistory } from 'vue-router' import { constRoutes } from '@/router/constRoutes' const router = createRouter({ history: createWebHistory(import.meta.env.BASE_URL), routes: constRoutes }) export default router
// utils/map-menus.js // --------------------------------------- //导出方法,menuList是线上路由,Routes第一次默认是本地路由 // --------------------------------------- import { asyncRoutes } from '@/router/asyncRoutes' // 添加redirect重定向 let redirect = '' // 匹配路由,添加对应线上传回来的参数 export function mapMenusToRoutes(menuList, Routes = asyncRoutes) { const routes = [] for (let item of Routes) { const m = menuList.find((menu) => item.name == menu.name) if (m) { // 线上按钮权限放在attr中 m.attr && m.attr.length && (item.attr = m.attr) item.id = m.id // ‘?.'判断是否有children且大于零 if (item.children?.length) { // 添加重定向 if (item.path.includes('/')) { redirect = item.path item.redirect = `${redirect}/${item.children[0].path}` } else { item.redirect = `${redirect}/${item.path}/${item.children[0].path}` } // 如果有children 则回调并赋值 item.children = mapMenusToRoutes(m.children, item.children) } routes.push(item) } } return routes }
&&&&后面是具体调用方式,因人而异,可自行选择
// stores/login.js import { defineStore } from 'pinia' import router from '@/router' import { notFound } from '@/router/constRoutes' import localCache from '@/utils/cache' import { mapMenusToRoutes } from '@/utils/map-menus' import { login, getInfo } from '@/api/user/login' export const useLoginStore = defineStore({ id: 'useLoginStore', state: () => ({ token: '', menuList: [], routeMenus: [] }), getters: { routeMenusGet() { return this.routeMenus } }, actions: { async LoginAction(loginForm) { // 1.实现登录逻辑 const { data: loginData } = await login(loginForm) this.token = loginData.token // 保存至localStorage,方法随意 localCache.setCache('token', this.token) // 2.跳转至首页 router.push('/home') }, // router.beforeEach获取菜单树 async getInfoAction() { const infoData = await getInfo({ token: this.token }) this.menuList = infoData.data.menuList this.addRouteMenus() }, // 动态加载路由 addRouteMenus() { this.routeMenus = mapMenusToRoutes(this.menuList) // vue3中只有addRoute for (let item of this.routeMenus) { router.addRoute(item) } // 最后添加,否则刷新请求线上路由时,还没有加载完,会直接定向到notFound router.addRoute(notFound) } } })
// src/permission.js // main.js中引入次文件 import '@/permission' import router from './router' import localCache from '@/utils/cache' import { useLoginStore } from '@/stores/user/login' router.beforeEach(async (to, from, next) => { document.title = `${to.meta.title}` if (to.path === '/login') { // 清空localStorage localCache.clearCache() next() } else { const token = localCache.getCache('token') if (!token) { next(`/login`) } else { const loginStore = useLoginStore() if (loginStore.routeMenus.length) { next() } else { // 如果没有路由,调用动态加载路由 try { await loginStore.getInfoAction() next({ ...to, replace: true }) } catch (error) { next(`/login`) } } } } })
总结
以上为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。