vue-element-admin动态菜单(后台获取)

vue-element-admin动态菜单(后台获取),此教程面向纯小白攻略,不要嫌我啰嗦,翻到自己需要的地方即可

前提

vue-element-admin官网: vue-element-admin (gitee.io)

vue-element-admin页面展示:vue-element-adminVue Element Admin

vue-element-admin下载:PanJiaChen/vue-element-admin

安装依赖报错解决方案:vue-element-admin项目安装依赖报错

首先我们拿到项目,得了解一下目录结构

他是通过src->router->index.js,根据路由来进行页面的跳转

在这里插入图片描述

我们查看一下里面的文件,再对比一下项目的目录

export const asyncRoutes = [{path: '/permission',component: Layout,redirect: '/permission/page',alwaysShow: true, // will always show the root menuname: 'Permission',meta: {title: 'Permission',icon: 'lock',roles: ['admin', 'editor'] // you can set roles in root nav},children: [{path: 'page',component: () => import('@/views/permission/page'),name: 'PagePermission',meta: {title: 'Page Permission',roles: ['admin'] // or you can only set roles in sub nav}},{path: 'directive',component: () => import('@/views/permission/directive'),name: 'DirectivePermission',meta: {title: 'Directive Permission'// if do not set roles, means: this page does not require permission}},{path: 'role',component: () => import('@/views/permission/role'),name: 'RolePermission',meta: {title: 'Role Permission',roles: ['admin']}}]},{path: '/icon',component: Layout,children: [{path: 'index',component: () => import('@/views/icons/index'),name: 'Icons',meta: { title: 'Icons', icon: 'icon', noCache: true }}]},/** when your routing map is too long, you can split it into small modules **/componentsRouter,chartsRouter,nestedRouter,tableRouter,{path: '/example',component: Layout,redirect: '/example/list',name: 'Example',meta: {title: 'Example',icon: 'el-icon-s-help'},children: [{path: 'create',component: () => import('@/views/example/create'),name: 'CreateArticle',meta: { title: 'Create Article', icon: 'edit' }},{path: 'edit/:id(\\d+)',component: () => import('@/views/example/edit'),name: 'EditArticle',meta: { title: 'Edit Article', noCache: true, activeMenu: '/example/list' },hidden: true},{path: 'list',component: () => import('@/views/example/list'),name: 'ArticleList',meta: { title: 'Article List', icon: 'list' }}]},{path: '/tab',component: Layout,children: [{path: 'index',component: () => import('@/views/tab/index'),name: 'Tab',meta: { title: 'Tab', icon: 'tab' }}]},{path: '/error',component: Layout,redirect: 'noRedirect',name: 'ErrorPages',meta: {title: 'Error Pages',icon: '404'},children: [{path: '401',component: () => import('@/views/error-page/401'),name: 'Page401',meta: { title: '401', noCache: true }},{path: '404',component: () => import('@/views/error-page/404'),name: 'Page404',meta: { title: '404', noCache: true }}]},{path: '/error-log',component: Layout,children: [{path: 'log',component: () => import('@/views/error-log/index'),name: 'ErrorLog',meta: { title: 'Error Log', icon: 'bug' }}]},{path: '/excel',component: Layout,redirect: '/excel/export-excel',name: 'Excel',meta: {title: 'Excel',icon: 'excel'},children: [{path: 'export-excel',component: () => import('@/views/excel/export-excel'),name: 'ExportExcel',meta: { title: 'Export Excel' }},{path: 'export-selected-excel',component: () => import('@/views/excel/select-excel'),name: 'SelectExcel',meta: { title: 'Export Selected' }},{path: 'export-merge-header',component: () => import('@/views/excel/merge-header'),name: 'MergeHeader',meta: { title: 'Merge Header' }},{path: 'upload-excel',component: () => import('@/views/excel/upload-excel'),name: 'UploadExcel',meta: { title: 'Upload Excel' }}]},{path: '/zip',component: Layout,redirect: '/zip/download',alwaysShow: true,name: 'Zip',meta: { title: 'Zip', icon: 'zip' },children: [{path: 'download',component: () => import('@/views/zip/index'),name: 'ExportZip',meta: { title: 'Export Zip' }}]},{path: '/pdf',component: Layout,redirect: '/pdf/index',children: [{path: 'index',component: () => import('@/views/pdf/index'),name: 'PDF',meta: { title: 'PDF', icon: 'pdf' }}]},{path: '/pdf/download',component: () => import('@/views/pdf/download'),hidden: true},{path: '/theme',component: Layout,children: [{path: 'index',component: () => import('@/views/theme/index'),name: 'Theme',meta: { title: 'Theme', icon: 'theme' }}]},{path: '/clipboard',component: Layout,children: [{path: 'index',component: () => import('@/views/clipboard/index'),name: 'ClipboardDemo',meta: { title: 'Clipboard', icon: 'clipboard' }}]},{path: 'external-link',component: Layout,children: [{path: 'https://github.com/PanJiaChen/vue-element-admin',meta: { title: 'External Link', icon: 'link' }}]},// 404 page must be placed at the end !!!{ path: '*', redirect: '/404', hidden: true }
]

我拿一部分来跟目录做一下对比,下面我将参数讲解一下

在这里插入图片描述

各个参数的意思

有子目录的目录,以最常见的table举例,table在这里,ctrl+左键点进去就行

在这里插入图片描述

如果使用的 vscode 跳转不了,他的目录是 src\router\modules\table.js

参数与目录的对照

在这里插入图片描述

动态菜单思路

我们要做到的是,根据后端返回的json对象,动态的显示目录

而vue-element-admin,是写死了的菜单,所以我们调用后端接口,实现目录的拼接,最终达到实现动态菜单的目的

那么我们就要仿造router目录下index.js文件,动态的生成相似的json对象

生成动态菜单,修改文件

修改src/store/modules目录下的permission.js文件,这个文件就是用来生成菜单的(上面的index.js只是目录的结构,并不是生成的途径)

源文件

//这个asyncRoutes不眼熟吗,不就是刚才我们看的目录结构吗
import { asyncRoutes, constantRoutes } from '@/router'//不管
function hasPermission(roles, route) {if (route.meta && route.meta.roles) {return roles.some(role => route.meta.roles.includes(role))} else {return true}
}//不管
export function filterAsyncRoutes(routes, roles) {const res = []routes.forEach(route => {const tmp = { ...route }if (hasPermission(roles, tmp)) {if (tmp.children) {tmp.children = filterAsyncRoutes(tmp.children, roles)}res.push(tmp)}})return res
}
//不管
const state = {routes: [],addRoutes: []
}
//不管
const mutations = {SET_ROUTES: (state, routes) => {state.addRoutes = routesstate.routes = constantRoutes.concat(routes)}
}
//重要的是这个,这里不用看,但你要知道这里很重要,是加载目录的地方
const actions = {generateRoutes({ commit }, roles) {return new Promise(resolve => {let accessedRoutesif (roles.includes('admin')) {accessedRoutes = asyncRoutes || []} else {accessedRoutes = filterAsyncRoutes(asyncRoutes, roles)}commit('SET_ROUTES', accessedRoutes)resolve(accessedRoutes)})}
}
//不管
export default {namespaced: true,state,mutations,actions
}

我修改的permission.js文件,下面有json文件,一定要对照着看,不然看不懂

import { asyncRoutes, constantRoutes } from '@/router'import { authMenu } from '@/api/user'// 【新加入】引入请求,后面有文件,先不慌
import Layout from '@/layout'// 【新加入】引入layout// 这里是因为我之前没用动态菜单的时候报错,从网上搜的,改了点,好像也不太重要
function hasPermission(roles, route) {if (route.meta && route.meta.roles) {if (route.meta.roles.indexOf(roles) > -1) {return true} else {return false}// return roles.some(role => route.meta.roles.includes(role))} else {return true}
}//这里自己写方法,作用就是向 asyncRoutes 插入路由,达到动态路由的效果
/*** 【新加入】后台查询的菜单数据拼装成路由格式的数据* @param routes*/
export function generaMenu(routes, data) {//data挨个遍历data.forEach(item => {//path不为空的话,就新建一个对象,装数据if (item.path !== '') {//这个就仿照目录的机构,搭建const menu = {path: item.path,component: Layout, //这个不用写data里面的内容,引用就行了redirect: item.redirect,children: [],name: item.name,meta: item.meta}//遍历子标签,并加入到主目录的children中去item.children.forEach(item => {const menu2 = {path: item.path,component: (resolve) => require([`@/views${item.component}`], resolve),name: item.name,meta: item.meta}//加入到主目录的children中去menu.children.push(menu2)})//追加routes.push(menu)}})
//把404加到最后,因为作者说  // 404 page must be placed at the end !!!const menu3 = {path: '*',redirect: '/404',hidden: true}//追加routes.push(menu3)
}//不看
export function filterAsyncRoutes(routes, roles) {const res = []routes.forEach(route => {const tmp = { ...route }if (hasPermission(roles, tmp)) {if (tmp.children) {tmp.children = filterAsyncRoutes(tmp.children, roles)}res.push(tmp)}})return res
}
//不看
const state = {routes: [],addRoutes: []
}
//不看
const mutations = {SET_ROUTES: (state, routes) => {state.addRoutes = routesstate.routes = constantRoutes.concat(routes)}
}const actions = {generateRoutes({ commit }, roles) {return new Promise(resolve => {// 【新加入】开始const loadMenuData = []// 先查询后台并返回左侧菜单数据并把数据添加到路由,authMenu(state.token)后面会写authMenu(state.token).then(response => {let data = response//我的code为100200为正常if (response.code !== 100200) {this.$message({message: '菜单数据加载异常',type: 0})} else {//获取目录的jsondata = response.data//把data的数据拷贝到loadMenuData里面Object.assign(loadMenuData, data)//把asyncRoutes的数据拷贝到tempAsyncRoutes里面const tempAsyncRoutes = Object.assign([], asyncRoutes)// 最最重要的,把loadMenuData追加到tempAsyncRoutes后面generaMenu(tempAsyncRoutes, loadMenuData)//定义accessedRouteslet accessedRoutes// 把 tempAsyncRoutes 的值给 accessedRoutes ,并输出// eslint-disable-next-line prefer-constaccessedRoutes = tempAsyncRoutes || []//下面这些就是加载目录了commit('SET_ROUTES', accessedRoutes)resolve(accessedRoutes)}})}).catch(error => {console.log(error)})}
}export default {namespaced: true,state,mutations,actions
}

JSON文件,后台返回的值

{"code":100200,"msg":"返回成功","data":[{"path":"/maintenance","component":"Layout","redirect":"","name":"","meta":{"title":"","icon":"table"},"children":[{"path":"/maintenance-task-management","component":"/table/complex-table","name":"maintenance-task-management""meta":{"title":"维修任务管理"}}]},{"path":"/complete","component":"Layout","redirect":"","name":"","meta":{"title":"","icon":"table"},"children":[{"path":"/complete-maintenance-management","component":"/table/complex-table","name":"complete-maintenance-management""meta":{"title":"维修完成管理"}}]},{"path":"/plant","component":"Layout","redirect":"","name":"","meta":{"title":"","icon":"table"},"children":[{"path":"/plant-maintenance-management","component":"/table/complex-table","name":"plant-maintenance-management""meta":{"title":"送厂维修管理"}}]},{"path":"/device","component":"Layout","redirect":"","name":"","meta":{"title":"","icon":"table",},"children":[{"path":"/device-information-search","component":"/table/complex-table","name":"device-information-search""meta":{"title":"设备信息查找"}}]}]
}

添加authMenu接口

引入后台接口的方法(也就是封装好的axios,然后把接口统一写在一个js文件里,用的时候直接引入,方便后期维护)

首先在src->api>user.js,加入一个接口方法

import request from '@/utils/request'export function login(data) {return request({url: '/fix/user/login',method: 'post',data})
}export function getInfo(token) {return request({url: '/fix/user/info',method: 'get',params: { token }})
}export function logout() {return request({url: '/fix/user/logout',method: 'post'})
}
//这里加一个,根据data的不同,后台会返回不同的字符串结果,动态菜单完成
export function authMenu(data) {return request({url: '/fix/user/selectMenu',method: 'post',data})
}

修改index.js中的asyncRoutes方法,使其为空,要我们动态的加入菜单

export const asyncRoutes = [
]

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/66082.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Redis复制

在Redis中,用户可以通过执行SLAVEOF命令或者设置slaveof选项,让一个服务器去复制(replicate) 另一个服务器,我们称呼被复制的服务器为主服务器(master),而对主服务器进行复制的服务器则被称为从服务器(slave),如下图所…

什么是伪类选择器?

聚沙成塔每天进步一点点 ⭐ 专栏简介⭐ 伪类选择器⭐ 一些常见的伪类选择器示例::hover:active:focus:nth-child(n):first-child 和 :last-child ⭐ 写在最后 ⭐ 专栏简介 前端入门之旅:探索Web开发的奇妙世界 记得点击上方或者右侧链接订阅本专栏哦 几何…

关于Java中synchronized的实现原理

并发编程的三个理念 原子性:一个操作要么全部完成,要么全部失败。可见性:当一个线程对共享变量进行修改后,其他线程也应立刻看到。有序性:程序按照顺序执行 synchronized基本使用 修饰静态方法,锁的是类…

pycorrector一键式文本纠错工具,整合了BERT、MacBERT、ELECTRA、ERNIE等多种模型,让您立即享受纠错的便利和效果

pycorrector:一键式文本纠错工具,整合了Kenlm、ConvSeq2Seq、BERT、MacBERT、ELECTRA、ERNIE、Transformer、T5等多种模型,让您立即享受纠错的便利和效果 pycorrector: 中文文本纠错工具。支持中文音似、形似、语法错误纠正,pytho…

每天一道leetcode:300. 最长递增子序列(动态规划中等)

今日份题目: 给你一个整数数组 nums ,找到其中最长严格递增子序列的长度。 子序列 是由数组派生而来的序列,删除(或不删除)数组中的元素而不改变其余元素的顺序。例如,[3,6,2,7] 是数组 [0,3,1,6,2,2,7] …

【力扣每日一题】1572. 矩阵对角线元素的和 8.11打卡

文章目录 题目思路代码 题目 1572. 矩阵对角线元素的和 难度: 简单 描述: 给你一个正方形矩阵 mat,请你返回矩阵对角线元素的和。 请你返回在矩阵主对角线上的元素和副对角线上且不在主对角线上元素的和。 返回合并后的二叉树。 注意…

Python web实战之Django 的缓存机制详解

关键词:Python、Web 开发、Django、缓存 1. 缓存是什么?为什么需要缓存? 在 Web 开发中,缓存是一种用于存储数据的临时存储区域。它可以提高应用程序的性能和响应速度,减轻服务器的负载。 当用户访问网页时&#xff…

【金融量化】对企业进行估值的方法有哪些?

估值的方法有哪些? 如何对企业进行估值?有2个方法估算。 1 绝对估值法 它是一种定价模型,用于计算企业的内在价值。 比如说你可以根据公司近N年的现金流情况。借此去预测未来N年的现金流情况。所有的现金流数据都可以在年报上查询到。最后…

adb 通过wifi连接手机

adb 通过wifi连接手机 1. 电脑通过USB线连接手机2. 手机开启USB调试模式,开启手机开发者模式3.手机开启USB调试模式 更多设置-》开发者选项-》USB调试4.点击Wi-Fi 高级设置,可以查看到手机Wi-Fi的IP地址,此IP地址adb命令后面的ip地址&#xf…

【D3S】REST接口文档自动生成 - 集成smart-doc并同步配置到Torna

目录 一、引言二、maven插件三、smart-doc.json配置四、smart-doc-maven-plugin相关命令五、推送文档到Torna六、通过Maven Profile简化构建 一、引言 D3S(DDD with SpringBoot)为本作者使用DDD过程中开发的框架,目前已可公开查看源码&#…

TCP/IP 下的计算机网络江湖

〇、引言 在当今数字化时代,计算机网络宛如广袤江湖,涵盖着五大门派:物理层、数据链路层、网络层、传输层和应用层。每个门派独具技能,共同构筑着现代网络的框架。物理层宛如江湖基石,将比特流传输;数据链路层如武林传承,组织数据帧传递;网络层则像导航大师,寻找传送路…

js的练习

这里写目录标题 工具代码运行结果 工具 HBuilder X 代码 <!DOCTYPE html> <html><head><meta charset"utf-8"><title></title><script>window.onload function() // 需要在body加载完成之后&#xff0c;才能通过docu…