vue3动态路由

思路

1.登录获取用户所拥有菜单权限
2.促发action暂存菜单信息
3.创建全局路由前置守卫
4.合理利用next

1.登录获取路由信息

  • 一、接口返回数据:
[
    {
        "path":"/system",
        "name":"System",
        "children":[
            {
                "path":"/system/userManagement",
                "name":"UserManagement",
                "component":"() => import("../views/system/userManagement/index.vue"
            },
            {
                "path":"/system/menuManagement",
                "name":"MenuManagement",
                "component":"() => import("../views/system/menuManagement/index.vue"
            }
        ]
    }
]
  • 二、store/index.ts
import { defineStore } from 'pinia'
import { addRoute } from '@/router/index'

// 路由状态管理
export const useLoginSettingStore = defineStore('loginSettingStore', {
	state: () => ({
		USER_ROUTES: JSON.parse(localItem.getItem('USER_ROUTES')) || [],
	}),
	actions: {
		setRoutes() {
			return request({
				url: '/api/routers',
			}).then((res: any) => {
				this.USER_ROUTES = res
				localStorage.setItem('USER_ROUTES', JSON.stringify(res))
				addRoute(res)
			})
		},                                                  
	},
})

  • 二、login.vue - 接口调用获取登录信息
import { useLoginSettingStore } from '@/store/useLoginSetting'
const { setRoutes } = useLoginSettingStore()

// 促发actions
setRoutes().then(() => {
   router.replace(/system)
})
  • 三、静态路由配置
    router/index.ts
import { createRouter, createWebHistory, RouteRecordRaw } from 'vue-router'

const routes: Array<RouteRecordRaw> = [
	{
		path: '/',
		name: 'Home',
		component: () => import('@/views/Home.vue')
	},
	{
		path: '/login',
		name: 'Login',
		component: () => import('../views/Login.vue')
	},
	{
		path: '/404',
		name: '404',
		component: () => import('@/views/404.vue'),
		meta: {},
	},
	{
		path: '/:pathMatch(.*)',
		redirect: '/404',
		meta: {},
	},
	{
		path: '/:catchAll(.*)',
		redirect: '/404',
		meta: {},
	},
]

const router = createRouter({
	history: createWebHistory(),
	routes,
})

// Vite 支持使用特殊的 import.meta.glob 函数从文件系统导入多个模块:
const _modules = import.meta.glob('../views/**/**.vue')
const initRouter = (routers: any) => {
	if (!routers) return []
	routers.forEach((route: any) => {
		if (route.component) {
			route.component = _modules[route.component]
		}
		if (route.children != undefined && route.children.length > 0) {
			initRouter(route.children)
		}
	})
	return routers
}

export const addRoute = (routes: any) => {
	const routers = initRouter(routes)
	routers.forEach(async (route: any) => {
		if (!router.hasRoute(route.name)) {
			router.addRoute(route)
		}
	})
}

注: 在Vue3中,废弃了 addRoutes() 方法,只保留了 addRoute() 单个添加路由配置的方法。

  • 四、路由守卫
router.beforeEach((to: any, from: any, next: any) => {
	let token = localStorage.getItem('token')
	let routes = localStorage.getItem('USER_ROUTES')
	let isLoadRouters = true
	if (!token) {
		next(‘/login’)
	}
	if (to.path == '/login') {
		next()
	}
	// 没有路由信息时,需重新请求
	if (routes.length === 0) {
		setRoutes().then(() => {
			next({ ...to, replace: true })
		})
	} else {
		// 判断是否已添加路由
		if (isLoadRouters) {
			// 添加动态路由
			addRoute(routes)
			isLoadRouters = false
			// 解决刷新页面空白
			next({ ...to, replace: true })
		} else {
			// 路由已添加,可直接跳转
			next()
		}
	}
})

注:
每一次导航路由的跳转,都会经过一遍路由全局守卫,如果直接去使用next(路径),就会不断进行路由判断,进入无限循环

通过addRoute动态添加的路由如果刚添加完就立刻放行,此时addRoute还没有执行结束,因此找不到刚添加的路由,就会导致白屏,因此需要重新访问一遍路由才行

next({…to})能够递归调用beforeEach直到找到对应的路由。

replace:true是防止在递归调用期间用户点击浏览器的后退按钮产生错误。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值