文章简介
针对vue-router4的简单配置,基本路由的配置和后端获取路由后的渲染进行简单的配置,路由跳转前的验证功能。
安装
npm install vue-router@4
配置
- src 文件下创建 router/index.js 文件。
import { createRouter, createWebHashHistory } from 'vue-router'
// 本地静态路由配置
export const routes = [
{
path: '/',
redirect: '/home'
},
{
path: '/login',
component: () => import('@/views/login.vue'),
},
{
path: '/home',
component: () => import('@/views/home.vue'),
},
{
path: '/:pathMatch(.*)*',
component: () => import('@/views/404.vue'),
}
]
// 创建路由实例
const router = createRouter({
history: createWebHashHistory(),
routes: routes,
})
export default router
- main.js 中配置
// 引入路由
import router from './router'
app.use(router)
路由拦截配置
可以写在 router/index.js 中,也可以单独创建一个文件 permission.js 写,根据个人需求决定, 文件名称按你喜欢的写,单独写的话要在 main.js 中引入。
...
... 省略以上代码
// 配置路由白名单
let whiteList = ['/login']
// 路由拦截
router.beforeEach((to, from, next) => {
// 白名单-> 直接放行
if (whiteList.includes(to.path)) {
return next()
}
// 如果没有token,跳转到登录页面并携带当前路由的path作为参数
if (!token) {
return next('/login?redirect=' + to.path)
}
// 有token,有菜单 -> 直接放行
if (menuList && userStore.menuList.length > 0) {
return next()
}
// 有token,无菜单 -> 请求路由数据并渲染路由
loadMenu(to, next)
})
// 路由跳转后的事件
router.afterEach((to, from) => {
// ...操作根据需求决定
})
动态请求路由配置
// 处理请求的数据
function asyncRoutesHandler(routes) {
return routes.map(route => {
// 先处理菜单的属性(meta,keepAlive等)=> 处理逻辑省略。。。
// 动态加载组件
if (route.component === 'Layout') {
route.component = Layout
} else {
const component = route.component
route.component = modules[`/src/views${component}.vue`]
}
// 递归处理子路由
if (route.children && route.children.length > 0) {
route.children = asyncRoutesHandler(route.children)
}
// 返回处理后的路由
return route
})
}
// 请求菜单数据
async function loadMenu(to, next) {
let res = await getMenuList()
// 处理请求的数据(layout、children、path、name等)
let asyncRoutes = asyncRoutesHandler(res.data)
// 添加路由
asyncRoutes.forEach(item => {
router.addRoute(item)
})
// 添加404页面
router.addRoute(NotFound)
// 添加到options.routes中,防止渲染菜单的时候拿不到
router.options.routes = [...routes, ...asyncRoutes]
// ...to浅拷贝to的对象 , replace: true 禁止浏览器记录路由记录,防止重复刷新
next({ ...to, replace: true })
}
完整代码如下
import { createRouter, createWebHashHistory } from 'vue-router'
const modules = import.meta.glob('/src/views/**/**.vue')
// 404页面提出来最后插入,防止先路由先匹配404页面
const NotFound = {
path: '/:pathMatch(.*)*',
name: '404',
component: () => import('@/views/404.vue'),
}
// 本地静态路由配置
const routes = [
{
path: '/',
redirect: '/home'
},
{
path: '/home',
component: () => import('@/views/home/index.vue'),
},
]
// 创建路由实例
const router = createRouter({
history: createWebHashHistory(),
routes: routes,
})
// 配置路由白名单
let whiteList = ['/login']
// 路由拦截
router.beforeEach((to, from, next) => {
// 白名单-> 直接放行
if (whiteList.includes(to.path)) {
return next()
}
// 如果没有token,跳转到登录页面并携带当前路由的path作为参数
if (!token) {
return next('/login?redirect=' + to.path)
}
// 有token,有菜单 -> 直接放行
if (menuList && userStore.menuList.length > 0) {
return next()
}
// 有token,无菜单 -> 请求路由数据并渲染路由
loadMenu(to, next)
})
// 处理请求的数据
function asyncRoutesHandler(routes) {
return routes.map(route => {
// 先处理菜单的属性(meta,keepAlive等)
// 处理逻辑省略。。。
// 动态加载组件
if (route.component === 'Layout') {
route.component = Layout
} else {
const component = route.component
route.component = modules[`/src/views${component}.vue`]
}
// 递归处理子路由
if (route.children && route.children.length > 0) {
route.children = asyncRoutesHandler(route.children)
}
// 返回处理后的路由
return route
})
}
// 请求菜单数据
async function loadMenu(to, next) {
// 这里会引入仓库,然后存储请求回来的路由,防止每次刷新都请求
const userStore = useUserStore() // 存储路由数据的仓库 我用的pinia
let res = await getMenuList() // 请求路由数据
userStore.setMenuList(res.data) // 用自己的方法把数据塞到仓库就行
// 处理请求的数据(layout、children、path、name等)
let asyncRoutes = asyncRoutesHandler(res.data)
// 添加路由
asyncRoutes.forEach(item => {
router.addRoute(item)
})
// 添加404页面
router.addRoute(NotFound)
// 添加到options.routes中,防止渲染菜单的时候拿不到
router.options.routes = [...routes, ...asyncRoutes]
// ...to浅拷贝to的对象 , replace: true 禁止浏览器记录路由记录,防止重复刷新
next({ ...to, replace: true })
}
// 路由跳转后的事件
router.afterEach((to, from) => {
// ...操作根据需求决定
})
export default router