前言:
首先,我们需要知道,动态路由菜单并非一开始就写好的,而是用户登录之后获取的路由菜单再进行渲染,从而可以起到资源节约何最大程度的保护系统的安全性。
需要配合后端,如果后端的值不匹配,做成动态路由会很复杂。
第一部分: 获取到用户渲染的菜单路由数据
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 = res
window.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.路由前置守卫,根据自己的需要进行改动。