vue3 使用addRoute动态添加路由
我们在开发大型系统的时候一般都需要动态添加路由,功能页面一多的话,想必写死这种方法已经完全走不通了 今天就来介绍一下vue3 如何使用addRoute动态添加路由 基本的思
我们在开发大型系统的时候一般都需要动态添加路由,功能页面一多的话,想必写死这种方法已经完全走不通了
今天就来介绍一下vue3 如何使用addRoute动态添加路由
基本的思路:
通过后端拿到路由数据,遍历路由数据通过router.addRoute一个个的添加,同时将路由数据通过vuex缓存起来,当页面刷新时,从缓存里拿出路由数据再重新添加,同时配合路由守卫来跳页面
遇到的坑:
逻辑不当的情况下,很容易死循环
刷新页面后动态添加的路由页面空白
以下代码同时解决了上面两个所遇到的坑,便再此记录以下
//router/index.ts
import { createRouter, createWebHashHistory, RouteRecordRaw } from "vue-router";
import Layout from "@/layout/index.vue"
import { getMenuNav } from "@/utils/api"
import store from "@/store"
type RouteConfig = RouteRecordRaw & { hidden?: boolean };
const constantRouterMap: Array<RouteConfig> = [
{
path: "/",
component: Layout,
redirect: '/index',
name: 'Index',
meta: {
title: '首页',
affix: true,
},
children: [{
path: 'index',
name: 'Index',
component: () => import("@/views/index/index.vue"),
meta: {
title: '工作台',
affix: true,
},
}]
},
{
path: "/login",
name: 'Login',
component: () => import('@/views/user/login.vue'),
hidden: true,
}, {
path: "/404",
name: "notFound",
component: () => import('@/views/notfound.vue'),
meta: {
title: '页面不存在'
}
},
];
const router = createRouter({
history: createWebHashHistory(process.env.BASE_URL),
routes: constantRouterMap,
});
let isF = false //这个是用于判断动态路由是否已经被获取
router.beforeEach(async (to, from, next) => {
if (to.path == '/login') {
next();
}
const token = localStorage.getItem('token');
if (!token) {
next({ path: '/login' });
} else {
if (isF) {
next();
} else {
const res = await getMenuNav();
const addRoute = addData(res.data);//获取动态路由
// 获取当前默认路由
const currenRoutes = router.options.routes
add.forEach((item: any) => {
// has用于判断当前路由中是否已经具有,避免重复
const has = currenRoutes.some(it => it.path == item.path)
if (!has) {
currenRoutes.push(item)
}
})
// 将404添加进去
//现在才添加的原因是:作为一级路由,当刷新,动态路由还未加载,路由就已经做了匹配,找不到就跳到了404
if (currenRoutes[currenRoutes.length - 1].path != '/:catchAll(.*)') {
currenRoutes.push({ path: "/:pathMatch(.*)", redirect: "/404" });
}
// 将新生成的路由替换原路由
currenRoutes.forEach(item => {
router.addRoute(item)
})
// 将新生成的路由保存到vuex中
store.dispatch('setRoutes', currenRoutes);
// 更改控制生成路由次数的值
isF = true
// 跳转
//确保addRoute()时动态添加的路由已经被完全加载上去,不然刷新页面可能会导致空白
next({ ...to, replace: true });
// 当然在这一步也可以是去判断一下to.matched是否含有数据,如果没有再触发一次beforeEach
// if(to.matched.length == 0){
// router.push(to.path)
// }else {next()}
}
}
})
export default router;
//store/index.ts
import { createStore } from "vuex";
import http from "@/utils/http";
export default createStore({
state: {
userInfo: {
nickname: '',
token: '',
group_id: 0
},
allRoutes: [],
},
mutations: {
SET_USERINFO: (state, data) => {
state.userInfo = data
},
SET_ROUTES(state, payload) {
state.allRoutes = payload
}
},
actions: {
//登录
LoginResult({ commit }, userInfo) {
return new Promise((resolve, reject) => {
http.request({ url: "/user/login", method: 'POST', data: userInfo }).then(
(res: any) => {
localStorage.setItem("token", res.data.token);
localStorage.setItem("nickname", res.data.nickname);
localStorage.setItem("headimg_url", res.data.headimg_url);
const userInfo = { nickname: res.data.nickname, token: res.data.token, group_id: res.data.group_id }
commit('SET_USERINFO', userInfo);
resolve(res);
},
(error: any) => {
reject(error)
}
).catch((error: any) => {
reject(error)
});
})
},
//登出
LogoutResult({ commit }) {
return new Promise((resolve, reject) => {
http.request({ url: "/user/logout", method: 'POST' }).then(
(res: any) => {
commit('SET_TOKEN', '');
localStorage.clear();
resolve(res);
},
(error: any) => {
reject(error)
}
).catch((error: any) => {
reject(error)
});
})
},
setRoutes({ commit }, data) {
commit('SET_ROUTES', data);
},
},
getters: {
userInfo: state => state.userInfo,
allRoutes: state => state.allRoutes,
},
modules: {},
});
如果需要再vue组件中使用,就是直接获取vuex中的数据就可以
const tabRoutes = computed(() => {
return store.getters.allRoutes.filter(route => route.meta);
});
// 然后将tabRoutes数组使用v-for在页面上遍历出来就ok了
原创文章,作者:ECHO陈文,如若转载,请注明出处:https://www.luweipai.cn/html/1646221364/