使用Vue2实现动态路由展示
思路:
- 后端返回树形数据
- 根据数据渲染左侧菜单
- 根据数据组装路由数据
注意:本文主要目的讲解是一种思路,如果有更好的实现方式,欢迎评论留言。
VUE2相关组件版本
这里需要注意下有版本关系,如果不对应会有不同的问题。
我使用的版本如下:
"axios": "^1.6.0",
"element-ui": "^2.15.14",
"node-sass": "^4.14.1",
"sass-loader": "^13.3.2",
"vue": "^2.6.14",
"vue-router": "^3.5.1",
"vuex": "^3.6.2"
原始菜单数据
数据库数据
树形数据
{
"code": 0,
"msg": "操作成功",
"data": [{
"id": 1,
"delFlag": 0,
"createTime": null,
"updateTime": null,
"pid": 0,
"title": "系统管理",
"component": null,
"sort": null,
"icon": "el-icon-setting",
"path": "system",
"children": [{
"id": 2,
"delFlag": 0,
"createTime": null,
"updateTime": null,
"pid": 1,
"title": "用户管理",
"component": "/system/User",
"sort": null,
"icon": "el-icon-user-solid\r\n",
"path": "user",
"children": null
}, {
"id": 3,
"delFlag": 0,
"createTime": null,
"updateTime": null,
"pid": 1,
"title": "菜单管理",
"component": "/system/Module",
"sort": null,
"icon": "el-icon-s-platform\r\n",
"path": "module",
"children": null
}]
}]
}
前端项目
在/router/index.js文件中
// 控制无限点击面包屑报错
const originalPush = VueRouter.prototype.push;
VueRouter.prototype.push = function push(location) {
return originalPush.call(this, location).catch((err) => err);
};
Vue.use(VueRouter);
配置静态路由
当页面进入后,默认进入登录页面。
//静态路由
const routes = [// 初始化重定向
{path: "/", component: Login},
{path: "/login", component: Login},
];
// 创建路由实例 导入配置项
const router = new VueRouter({
routes, mode: "history",
});
配置路由守卫
当用户登录成功后,请求菜单数据。开始组装路由
let isToken = true
router.beforeEach(async (to, from, next) => {
let token = getToken();
if (token) {
//获取路由并加载
if (isToken) {
//从后台获取到路由数据
let menuData = await reqListLeftSysMenu({});
let result = assertRouter(menuData.data);
setLeftMenu(JSON.stringify(menuData.data))
let test = [{
path: "/home",
component: Layout,
children: result
}];
router.addRoutes(test);
isToken = false;
next({
...to, // next({ ...to })的目的,是保证路由添加完了再进入页面 (可以理解为重进一次)
replace: true, // 重进一次, 不保留重复历史
})
}
}
next();
});
function assertRouter(data) {
//一级菜单处理
let result = [];
data.forEach(item => {
item.children.forEach(item1 => {
let childObj = {
path: "/" + item.path + "/" + item1.path,
component: () => import(`@/views${item1.component}`),
};
result.push(childObj);
})
})
return result;
}
关键代码是使用router.addRoutes来动态添加路由信息。
这里我使用了setLeftMenu来进行缓存原始菜单数据,用于左侧渲染菜单。
左侧路由回显代码
<el-menu style="height:500px"
default-active="2"
class="el-menu-vertical-demo"
background-color="#545c64"
text-color="#fff"
active-text-color="#ffd04b"
@select="handleSelect"
>
<el-submenu v-for="item in menuDataList" :index="item.path">
<template slot="title">
<i :class="item.icon"></i>
<span>{{ item.title }}</span>
</template>
<el-menu-item v-for="child in item.children" :index="child.path">
<i :class="child.icon"></i>
{{ child.title }}
</el-menu-item>
</el-submenu>
</el-menu>
<script>
import {getLeftMenu} from "@/utils/SessionStorage";
export default {
name: "Left",
created() {
this.menuDataList = JSON.parse(getLeftMenu());
},
data() {
return {
menuDataList: []
}
},
methods: {
handleSelect(key, keyPath) {
let jumpPath = "";
for (let i = 0; i < keyPath.length; i++) {
jumpPath += "/" + keyPath[i];
}
this.$router.push(jumpPath);
},
}
}
</script>
当点击左侧菜单后,进行跳转路由。
实现上方效果,则表示动态路由添加成功。