聊聊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
}
&&&&后面是具体调用方式,因人而异,可自行选择 {#heading-3}
// 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`)
}
}
}
}
})