前言:
首先,我们需要知道,动态路由菜单并非一开始就写好的,而是用户登录之后获取的路由菜单再进行渲染,从而可以起到资源节约何最大程度的保护系统的安全性。
需要配合后端,如果后端的值不匹配,做成动态路由会很复杂。
第一部分: 获取到用户渲染的菜单路由数据
1.用户登录成功,获取到用户的菜单路由。
res.meauList(用户菜单数据)
2.菜单数据格式:
"meauList": [{"id": 1,"meauid": "cd11111","name": "Index","path": "/index","component": "components/Index.vue","role": "student","meta": {"title": "学生首页","icon": "dataAnalysis"},"children": ""},{"id": 2,"meauid": "cd22222","name": "Apply","path": "/apply","component": "components/Apply.vue","role": "student","meta": {"title": "实习申请","icon": "document"},"children": ""},{"id": 3,"meauid": "cd33333","name": "Summary","path": "/summary","component": "components/Summary.vue","role": "student","meta": {"title": "实习总结","icon": "edit"},"children": ""}]
3.如果有子路由则显示子路由
第二部分:存储菜单路由到Vuex,进行持久化管理
1.定义store文件下的index.js(如果定义的数据过多,可以进行拆分多个包,这里暂不拆分)
import { createStore } from 'vuex'export default createStore({state: {//菜单数据meauList: JSON.parse(window.localStorage.getItem('meauList'))},getters: {},mutations: {//存储角色菜单setMeauList(state, res) {state.meauList = reswindow.localStorage.setItem('meauList', JSON.stringify(res))console.log('菜单数据', state.meauList);},},actions: {//如果是异步,则需要调取actions里面的方法addTagList(state, res) {console.log('store', res);},},modules: {}
})
2.登录时候获取到的菜单数据需要通过vuex进行保存
//存储菜单数据
this.$store.commit('setMeauList', res.meauList)
3.此处,因为使用了async awite使得登陆方法同步
,所以不需要使用 dispatch调用action的方法
4.此时数据已经保存到vuex,因为vuex是存在内存里面,所以刷新数据会丢失,我们可以存在缓存里面,或者可以使用vuex的插件来自动保存(这个自己可以去看看)。
第三部分:动态路由加载
1.路由分为静态路由何动态路由
2.静态路由就是登录页,不需要任何权限的路由,可以直接在程序中写死。
3.而动态路由需要根据不同用户进行加载。
4.静态路由定义:
import { createRouter, createWebHistory } from 'vue-router'
import store from '../store/index.js'const routes = [
//静态路由{path: '/login',name: 'Login',component: () => import('@/views/Login.vue'),meta: { title: '用户登录' },},
//父组件{path: '/', name: 'Home', component: Home, redirect: '/index',
//之后的都是子路由显示在此处
//如果你没有子路由,则不需要写上面这段}
}
4.动态路由加载:
//动态路由加载方法
const routerPackag = routers => {routers.filter(itemRouter => {if (itemRouter.component != "Login") {router.addRoute('Home', {path: `${itemRouter.path}`,name: itemRouter.name,component: () => import(`@/${itemRouter.component}`),//此处根据具体地址进行调整meta: itemRouter.meta});}// 是否存在子路由if (itemRouter.children && itemRouter.children.length) {routerPackag(itemRouter.children);}return true;});
}
//调用渲染动态组件方法
routerPackag(store.state.meauList);
5.路由前置守卫
router.beforeEach((to, from, next) => {console.log('to', to);//判断路由是否指向login,login路由不需要权限,可以直接访问if (to.path != '/login') {//如果路由不指向login,判断是否已经登录,有token字段存在if (window.localStorage.getItem('token')) {//此处可忽略//store.commit('addTagList', to)next()} else {//未登录,导航到login登录页next('/login')}} else {//如果指向login地址,直接放行next()}
})
6.路由前置守卫,根据自己的需要进行改动。