Vue动态路由实现左侧菜单

Vue动态路由实现左侧菜单

一、后端代码

1、后台Controller代码,从sys_menu获取菜单信息

/** * 获取路由信息

* * @return 路由信息

*/

@GetMapping("getRouters")

public AjaxResult getRouters() {

//获取用户身份信息

LoginUser loginUser = tokenService.getLoginUser(ServletUtils.getRequest());

// 用户信息

SysUser user = loginUser.getUser();

// 根据用户ID获取对应的菜单信息列表 List menus = menuService.selectMenuTreeByUserId(user.getUserId() );

// 将获取的菜单信息列表封装成前端所需要的格式

return AjaxResult.success(menuService.buildMenus(menus));

}

2、后台menuService 对应部分代码

/** * 构建前端路由所需要的菜单 * * @param menus 菜单列表 * @return 路由列表 */ @Override

public List buildMenus(List menus)

{

List routers = new LinkedList();

for (SysMenu menu : menus) {

RouterVo router = new RouterVo(); //router.setHidden("1".equals(menu.getVisible())); router.setName(getRouteName(menu)); router.setPath(getRouterPath(menu)); router.setComponent(getComponent(menu));

router.setMeta(new MetaVo(menu.getMenuName(), menu.getIcon(), true));

List cMenus = menu.getChildren();

if (!cMenus.isEmpty() && cMenus.size() > 0 && UserConstants.TYPE_DIR.equals(menu.getMenuType()))

{

router.setAlwaysShow(true); router.setRedirect("noRedirect"); router.setChildren(buildMenus(cMenus));

} else if (isMeunFrame(menu))

{

List childrenList = new ArrayList();

RouterVo children = new RouterVo(); children.setPath(menu.getPath()); children.setComponent(menu.getComponent()); children.setName(StringUtils.capitalize(menu.getPath()));

children.setMeta(new MetaVo(menu.getMenuName(), menu.getIcon(), true)); childrenList.add(children); router.setChildren(childrenList);

}

routers.add(router);

}

return routers;

}

/** * 获取路由名称

* * @param menu 菜单信息

* @return 路由名称

*/

public String getRouteName(SysMenu menu) {

String routerName = StringUtils.capitalize(menu.getPath());

// 非外链并且是一级目录(类型为目录)

if (isMeunFrame(menu)) {

routerName = StringUtils.EMPTY;

}

return routerName;

}

/** * 获取路由地址

* * @param menu 菜单信息

* @return 路由地址

*/

public String getRouterPath(SysMenu menu) {

String routerPath = menu.getPath();

// 非外链并且是一级目录(类型为目录)

if (0 == menu.getParentId().intValue() && UserConstants.TYPE_DIR.equals(menu.getMenuType()) ) {

routerPath = "/" + menu.getPath();

}

// 非外链并且是一级目录(类型为菜单) else if (isMeunFrame(menu)) {

routerPath = "/";

}

return routerPath;

}

/** * 获取组件信息

* * @param menu 菜单信息

* @return 组件信息

*/

public String getComponent(SysMenu menu) {

String component = UserConstants.LAYOUT;

if (StringUtils.isNotEmpty(menu.getComponent()) && !isMeunFrame(menu))

{

component = menu.getComponent();

} else if (StringUtils.isEmpty(menu.getComponent()) && isParentView(menu))

{

component = UserConstants.PARENT_VIEW;

}

return component;

}

/** * 是否为菜单内部跳转

* * @param menu 菜单信息

* @return 结果

*/

public boolean isMeunFrame(SysMenu menu) {

return menu.getParentId().intValue() == 0 && UserConstants.TYPE_MENU.equals(menu.getMenuType());

}

/** * 是否为parent_view组件

* * @param menu 菜单信息

* @return 结果 */

public boolean isParentView(SysMenu menu) {

return menu.getParentId().intValue() != 0 && UserConstants.TYPE_DIR.equals(menu.getMenuType());

}

二、前端代码

1、配置路由:在src的下面的router文件夹下创建index.js (\src\router\index.js) 文件 import Vue from 'vue'

import VueRouter from 'vue-router'

import Layout from '@/layout' Vue.use(VueRouter)

// 公用路由

export const constantRoutes = [

{

path: '/login',

name: 'login',

component: () => import('@/views/login'), hidden: true

},

{

path: '/register',

component: () => import('@/views/register'),

hidden: true

},

{

path: '/404',

component: () => import('@/views/error/404'),

hidden: true

},

{ path: '/401',

component: () => import('@/views/error/401'),

hidden: true

},

{ path: '',

component: Layout,

redirect: 'index',

children: [

{ path: 'index',

// component: () => import('@/views/index'),

component: (resolve) => require(['@/views/index'], resolve),// 打包环境-主页

name: 'Index',

meta: { title: '首页', icon: 'dashboard', noCache: true, affix: true },

hidden: false } ] } ]

const router = new VueRouter({

mode: 'history',

// 去掉url中的#

scrollBehavior: () => ({ y: 0 }),

routes: constantRoutes })

export default router

2、在src下面创建permission.js (\src\permission.js) 文件


import router from './router'

import store from './store'

import NProgress from 'nprogress'

// Progress 进度条

import 'nprogress/nprogress.css'

// Progress 进度条样式

import { Message } from 'element-ui' import { getToken } from '@/utils/auth'

// 验权

const whiteList = ['/login'] // 不重定向白名单

router.beforeEach((to, from, next) => { NProgress.start()

if (getToken()) {

if (to.path === '/login') {

next({ path: '/' })

NProgress.done()

} else {

if (store.getters.roles.length === 0) {

store.dispatch('GetInfo').then(res => {

// 拉取用户信息

const menus = res.menus

const username = res.username

store.dispatch('GenerateRoutes', { menus, username }).then(accessRoutes => {

// 生成可访问的路由表

router.addRoutes(accessRoutes)

// 动态添加可访问路由表

global.antRouter = accessRoutes

// 将路由数据传递给全局变量,做侧边栏菜单渲染工作

next({ ...to, replace: true })

})

}).catch((err) => {

store.dispatch('LogOut').then(() => {

Message.error(err || 'Verification failed, please login again')

next({ path: '/' })

})

})

} else {

next()

} } } else {

if (whiteList.indexOf(to.path) !== -1) {

next()

} else {

next('/login')

NProgress.done()

} }

})

router.afterEach(() => {

NProgress.done()

// 结束Progress

})

3、在src下面store\modules文件夹下创建permission.js (\src\store\modules\permission.js) 文件

import { constantRoutes } from '@/router/index'

import { getRouters } from '@/api/menu'

import Layout from '@/layout/index'

import ParentView from '@/components/ParentView'

const permission = {

state: {

routers: [],

addRouters: []

},

mutations: {

SET_ROUTERS: (state, routers) => {

state.addRouters = routers

state.routers = constantRoutes.concat(routers)

} },

actions: {

GenerateRoutes ({ commit }, data) {

return new Promise(resolve => {

// 向后端请求路由数据

getRouters().then(res => {

const sdata = JSON.parse(JSON.stringify(res.data))

const accessedRoutes = filterAsyncRouter(sdata, false, true)

commit('SET_ROUTERS', accessedRoutes)

resolve(accessedRoutes)

}) })

} } }

// 遍历后台传来的路由字符串,转换为组件对象

function filterAsyncRouter (asyncRouterMap, lastRouter = false, type = false)

{

return asyncRouterMap.filter(route => {

if (route.component) {

// Layout ParentView 组件特殊处理

if (route.component === 'Layout') {

route.component = Layout

} else if (route.component === 'ParentView') {

route.component = ParentView

} else {

route.component = loadView(route.component)

}

}

if (route.children != null && route.children && route.children.length) {

route.children = filterAsyncRouter(route.children, route, type)

}

return true

}) }

export const loadView = (view) => {

return (resolve) => require([`@/views/${view}`], resolve)

}

export default permission

4、在src下面store文件夹下创建index.js (\src\store\index.js) 文件

import Vue from 'vue'

import Vuex from 'vuex'

import permission from './modules/permission'

import getters from './getters'

Vue.use(Vuex)

const store = new Vuex.Store({

modules: { permission }, getters

})

export default store

5、在src下面store文件夹下创建getters.js (\src\store\getters.js) 文件

const getters = {

addRouters: state => state.permission.addRouters,

routers: state => state.permission.routers

}

export default getters


6、在src下面store\modules文件夹下创建permission.js (\src\store\modules\permission.js) 文件

import { constantRoutes } from '@/router/index'

import { getRouters } from '@/api/menu'

import Layout from '@/layout/index'

import ParentView from '@/components/ParentView'

const permission = {

state: {

routers: [],

addRouters: []

},

mutations: {

SET_ROUTERS: (state, routers) => {

state.addRouters = routers

state.routers = constantRoutes.concat(routers)

}

},

actions: {

GenerateRoutes ({ commit }, data) {

return new Promise(resolve => {

// 向后端请求路由数据

getRouters().then(res => {

const sdata = JSON.parse(JSON.stringify(res.data))

console.log('sdata', sdata)

const accessedRoutes = filterAsyncRouter(sdata, false, true)

console.log('accessedRoutes', accessedRoutes)

commit('SET_ROUTERS', accessedRoutes)

resolve(accessedRoutes)

}) })

} } }


// 遍历后台传来的路由字符串,转换为组件对象

function filterAsyncRouter (asyncRouterMap, lastRouter = false, type = false) {

return asyncRouterMap.filter(route => {

if (route.component) {

// Layout ParentView 组件特殊处理

if (route.component === 'Layout') {

route.component = Layout

} else if (route.component === 'ParentView') {

route.component = ParentView

} else {

route.component = loadView(route.component)

}

}

if (route.children != null && route.children && route.children.length) {

route.children = filterAsyncRouter(route.children, route, type)

} return true

}) }

export const loadView = (view) => {

return (resolve) => require([`@/views/${view}`], resolve)

}

export default permission


7、在src下面layout文件夹下创建index.vue (\src\layout\index.vue) 文件


8、在src下面layout\components文件夹下创建AppMain.vue

(\src\layout\components\AppMain.vue) 文件

9、在src下面layout\components文件夹下创建Navbar.vue

(\src\layout\components\Navbar.vue) 文件


10、在src下面layout\components文件夹下创建index.js (\src\layout\components\index.js) 文件

export { default as AppMain } from './AppMain'

export { default as Navbar } from './Navbar'

export { default as sidebar } from './sidebar/index.vue'


11、在src下面layout\components\sidebar文件夹下创建index.vue (\src\layout\components\sidebar\index.vue) 文件


12、在src下面layout\components\sidebar文件夹下创建sidebarItem.vue (\src\layout\components\sidebar\sidebarItem.vue) 文件



效果如图:

发表评论
留言与评论(共有 0 条评论) “”
   
验证码:

相关文章

推荐文章