vue3+router 动态加载路由刷新失效的问题

499 阅读1分钟

1. 第一步:登录步骤就不多说了,调用获取动态路由接口将返回的动态路由数据通过pinia的setAsideRoutes方法保存用于渲染侧边菜单栏用,获取到动态路由数据的第一步也是要先保存到本地一份的 (pinia浏览器刷新状态会重置,到时可以从缓存读取),在这一步也可以顺带序列化动态路由数据,将本地组件映射到路由数据中并通过addRoute方法逐一添加

import { ref, computed, reactive } from 'vue'
import { defineStore } from 'pinia'
import map from "@/router/map.js"
import dynamicRouters from '@/router/dynamicRouters.js'
import router from '@/router/index.js'


export const useAppStore = defineStore('app', () => {
	const isCollapse = ref(false)
	const activePath = ref('/')
	const asideRoutes = ref([]) // 全局权限侧边菜单栏

	const formatAddRoutes = routes => {
		routes.forEach(item => {
			let routeName = item.component
			console.log('formatAddRoutes:',item.component,map[item.component])
			item.component = map[item.component]
			if (item.component === undefined) {
				ElMessage.error(`组件【${routeName}】加载失败`)
			}
			if (item?.children?.length) {
				formatAddRoutes(item.children)
			}
			router.addRoute(item)
		})
	}
	return {
		isCollapse,
		activePath,
		asideRoutes,
		setCollapse: _ => isCollapse.value = !isCollapse.value,
		setActivePath: path => activePath.value = path,
		setAsideRoutes: routes => {
			asideRoutes.value = routes || JSON.parse(localStorage.getItem('asideRoutes') || '[]')
			localStorage.setItem('asideRoutes', JSON.stringify(asideRoutes.value))
			formatAddRoutes(asideRoutes.value)
		},
	}
})

2. 需要在前置路由 beforeEach 中做拦截操作,代码很简单,需要设置一个标识,只要每次刷新浏览器或手动输入路由地址,这里的flag就会默认为true,调用pinia内部设置菜单路由方法重新添加动态路由

import { useAppStore } from '@/stores/app.js'
import { createRouter, createWebHistory } from 'vue-router'
const router = createRouter({
	history: createWebHistory(import.meta.env.BASE_URL),
	routes: [
		{
			path: '/login',
			name: 'login',
			component: _ => import( /* webpackChunkName: "test" */ '@/views/login/index.vue')
		},
		{
			path: '/:catchAll(.*)',
			name: 'error',
			component: _ => import( /* webpackChunkName: "test" */ '@/views/error/index.vue')
		}
	]
})
let flag = true // 解决动态路由刷新消失的问题
router.beforeEach((to,form,next) => {
	const appStore = useAppStore()
	appStore.setActivePath(to.fullPath)
	if(flag) {
		flag = false
		appStore.setAsideRoutes()
		next({path: to.fullPath}) // 这段代码很诡异,去掉后动态路由刷新就失效
	}
	next()
})

export default router