IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> Java知识库 -> SpringBoot + Spring Cloud +Vue 管理系统前端搭建(九、动态加载菜单) -> 正文阅读

[Java知识库]SpringBoot + Spring Cloud +Vue 管理系统前端搭建(九、动态加载菜单)

1、添加store

??????? 我们先添加几个store状态,后续需要用来共享使用

??????? 首先,我们在store/modules下的app.js中添加一个menuRouteLoaded状态,来判断是否加载过路由

??????? 然后在store、modules下新建一个menu.js,在index.js中引入,里面保存加载后的导航菜单数据。

menu.js代码如下:

export default {

state: {

navTree: [], // 导航菜单树

},

getters: {

},

mutations: {

setNavTree(state, navTree){ // 设置导航菜单树

state.navTree = navTree;

}

},

actions: {

}

}

在store/modules下新建一个user.js,在index.js中引入,里面保存加载后的用户权限数据。

user.js代码如下:

export default {

state: {

perms: [], // 用户权限标识集合

},

getters: {

},

mutations: {

setPerms(state, perms){ // 用户权限标识集合

state.perms = perms;

}

},

actions: {

}

}

index.js引入后的代码如下:

import Vue from 'vue'
import vuex from 'vuex'

Vue.use(vuex);

// 引入子模块
import app from './modules/app'
import user from './modules/user'
import menu from './modules/menu'

const store = new vuex.Store({
??? modules: {
??????? app: app,
??????? user: user,
??????? menu: menu
??? }
})

export default store

2、登录页面

打开登录页面Login.vue, 在登录接口设置菜单加载状态,要求重新登录之后重新加载菜单,

?3、导航守卫

??????? 路由对象router给我们提供beforeEach方法,可以在每次路由之前进行一些相关处理,也叫导航守卫,我们这里就通过导航守卫实现动态菜单的加载。

??????? 修改router/index.js文件,添加导航守卫,在每次路由时判断用户会话是否过期。如果登录有效且跳转到登录界面,就直接路由到主页;如果是非登录页面且会话过期,就跳到登录页面要求登录;否则,加载动态菜单和路由并路由到目标页面。

??????? 下面是router下index.js代码

import Vue from 'vue'
import Router from 'vue-router'
import Login from '@/views/Login'
import Home from '@/views/Home'
import NotFound from '@/views/404'
import api from '@/http/api'
import store from '@/store'

Vue.use(Router)

const router = new Router({
? routes: [
??? {
????? path: '/',
????? name: '首页',
????? component: Home,
????? children: []
??? },
??? {
????? path: '/login',
????? name: '登录',
????? component: Login
??? },
??? {
????? path: '/404',
????? name: 'notFound',
????? component: NotFound
??? }
? ]
})

router.beforeEach((to, from, next) => {
? // 登录界面登录成功之后,会把用户信息保存在会话
? // 存在时间为会话生命周期,页面关闭即失效。
? let userName = sessionStorage.getItem('user')
? if (to.path === '/login') {
??? // 如果是访问登录界面,如果用户会话信息存在,代表已登录过,跳转到主页
??? if(userName) {
????? next({ path: '/' })
??? } else {
????? next()
??? }
? } else {
??? if (!userName) {
????? // 如果访问非登录界面,且户会话信息不存在,代表未登录,则跳转到登录界面
????? next({ path: '/login' })
??? } else {
????? // 加载动态菜单和路由
????? addDynamicMenuAndRoutes(userName, to, from)
????? next()
??? }
? }
})

/**
* 加载动态菜单和路由
*/
function addDynamicMenuAndRoutes(userName, to, from) {
? if(store.state.app.menuRouteLoaded) {
??? console.log('动态菜单和路由已经存在.')
??? return
? }
? api.menu.findNavTree({'userName':userName})
? .then(res => {
??? // 添加动态路由
??? let dynamicRoutes = addDynamicRoutes(res.data)
??? router.options.routes[0].children = router.options.routes[0].children.concat(dynamicRoutes)
??? router.addRoutes(router.options.routes)
??? // 保存加载状态
??? store.commit('menuRouteLoaded', true)
??? // 保存菜单树
??? store.commit('setNavTree', res.data)
? }).then(res => {
??? api.user.findPermissions({'name':userName}).then(res => {
????? // 保存用户权限标识集合
????? store.commit('setPerms', res.data)
??? })
? })
? .catch(function(res) {
? })
}

/**
* 添加动态(菜单)路由
* @param {*} menuList 菜单列表
* @param {*} routes 递归创建的动态(菜单)路由
*/
function addDynamicRoutes (menuList = [], routes = []) {
?var temp = []
?for (var i = 0; i < menuList.length; i++) {
?? if (menuList[i].children && menuList[i].children.length >= 1) {
???? temp = temp.concat(menuList[i].children)
?? } else if (menuList[i].url && /\S/.test(menuList[i].url)) {
????? menuList[i].url = menuList[i].url.replace(/^\//, '')
????? // 创建路由配置
????? var route = {
??????? path: menuList[i].url,
??????? component: null,
??????? name: menuList[i].name,
??????? meta: {
????????? icon: menuList[i].icon,
????????? index: menuList[i].id
??????? }
????? }
????? try {
??????? // 根据菜单URL动态加载vue组件,这里要求vue组件须按照url路径存储
??????? // 如url="sys/user",则组件路径应是"@/views/sys/user.vue",否则组件加载不到
??????? let array = menuList[i].url.split('/')
??????? let url = ''
??????? for(let i=0; i<array.length; i++) {
????????? url += array[i].substring(0,1).toUpperCase() + array[i].substring(1) + '/'
??????? }
??????? url = url.substring(0, url.length - 1)
??????? route['component'] = resolve => require([`@/views/${url}`], resolve)
????? } catch (e) {}
????? routes.push(route)
?? }
?}
?if (temp.length >= 1) {
?? addDynamicRoutes(temp, routes)
?} else {
?? console.log('动态路由加载...')
?? console.log(routes)
?? console.log('动态路由加载完成.')
?}
?return routes
}

export default router

4、导航树组件

??????? 在components目录下新建一个导航树组件MenuTree,如下图:

?代码如下:

<template>

<el-submenu v-if="menu.children && menu.children.length >= 1" :index="'' + menu.id">

<template slot="title">

<i :class="menu.icon" ></i>

<span slot="title">{{menu.name}}</span>

</template>

<MenuTree v-for="item in menu.children" :key="item.id" :menu="item"></MenuTree>

</el-submenu>

<el-menu-item v-else :index="'' + menu.id" @click="handleRoute(menu)">

<i :class="menu.icon"></i>

<span slot="title">{{menu.name}}</span>

</el-menu-item>

</template>

<script>

import { getIFrameUrl, getIFramePath } from '@/utils/iframe'

export default {

name: 'MenuTree',

props: {

menu: {

type: Object,

required: true

}

},

methods: {

handleRoute (menu) {

// 通过菜单URL跳转至指定路由

this.$router.push("/" + menu.url)

}

}

}

</script>

<style scoped lang="scss">

</style>

5、在navBar.vue中添加导航菜单

添加后代码如下:

<template>

??<div class="menu-bar-container">

<!-- logo -->

<div class="logo" :style="{'background':themeColor}" @click="$router.push('/')"

:class="collapse?'menu-bar-collapse-width':'menu-bar-width'">

<img v-if="collapse" src="@/assets/logo.png"/> <div>{{collapse?'':appName}}</div>

</div>

<!-- 导航菜单 -->

<el-menu ref="navmenu" default-active="1" :class="collapse?'menu-bar-collapse-width':'menu-bar-width'"

:collapse="collapse" :collapse-transition="false" :unique-opened="true "

@open="handleopen" @close="handleclose" @select="handleselect">

<!-- 导航菜单树组件,动态加载菜单 -->

<menu-tree v-for="item in navTree" :key="item.id" :menu="item"></menu-tree>

</el-menu>

??</div>

</template>

<script>

import { mapState } from 'vuex'

import MenuTree from "@/components/MenuTree"

export default {

components:{

MenuTree

},

computed: {

...mapState({

appName: state=>state.app.appName,

themeColor: state=>state.app.themeColor,

collapse: state=>state.app.collapse,

navTree: state=>state.menu.navTree

})

},

methods: {

handleopen() {

console.log('handleopen')

},

handleclose() {

console.log('handleclose')

},

handleselect(a, b) {

console.log('handleselect')

}

}

}

</script>

<style scoped lang="scss">

.menu-bar-container {

position: fixed;

top: 0px;

left: 0;

bottom: 0;

z-index: 1020;

.el-menu {

position:absolute;

top: 60px;

bottom: 0px;

text-align: left;

// background-color: #2968a30c;

}

.logo {

position:absolute;

top: 0px;

height: 60px;

line-height: 60px;

background: #545c64;

cursor:pointer;

img {

width: 40px;

height: 40px;

border-radius: 0px;

margin: 10px 10px 10px 10px;

float: left;

}

div {

font-size: 25px;

color: white;

text-align: left;

padding-left: 20px;

}

}

.menu-bar-width {

width: 200px;

}

.menu-bar-collapse-width {

width: 65px;

}

}

</style>

好了,到此我们已经完成了动态菜单,下面我们进行测试

启动项目后,我们访问:http://localhost:8080/#/login,点击登录

?

?可以看到我们菜单已经加载好了

好啦,到此我们完成了动态菜单加载

看完记得点赞哦

  Java知识库 最新文章
计算距离春节还有多长时间
系统开发系列 之WebService(spring框架+ma
springBoot+Cache(自定义有效时间配置)
SpringBoot整合mybatis实现增删改查、分页查
spring教程
SpringBoot+Vue实现美食交流网站的设计与实
虚拟机内存结构以及虚拟机中销毁和新建对象
SpringMVC---原理
小李同学: Java如何按多个字段分组
打印票据--java
上一篇文章      下一篇文章      查看所有文章
加:2021-08-11 12:06:27  更:2021-08-11 12:06:34 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/23 5:28:05-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码