VUE-Element组件(二)NavMenu导航菜单

标签介绍:el-menu为导航菜单组件,el-menu-item表示无子菜单的菜单项,el-submenu表示有子菜单的菜单项。

一、使用NavMenu做为导航菜单,实现的不好会出现点击菜单跳转到新页面的情况。如果想要实现本页跳转,可以参考以下步骤:

1、菜单首页的路由需要做为其他菜单页的父级路由。如菜单页为index.vue,现有用户页user.vue,这个user和index的文件目录没有任何要求,但user的路由需要是index的子路由,如index路由为/index,user路由为/user,是不可以的,此时user的路由需要是/index/...,如下是我的路由实例:

 {
    path: '/menu',
    name: 'menu',
    hidden:true,
    component: () => import('@/views/menu/index'),
    children: [
      //给菜单页一个默认的菜单显示
      {
        path: '/user',
        redirect: 'user'
      },
     
      {
        path: '/menu/user',
        name: 'user',
        component: () => import('@/views/menu/user')
      },
       {
        path: '/menu/role',
        name: 'role',
        component: () => import('@/views/menu/role')
      },
    ]
  }

2、el-menu菜单组件标签加上如下配置: :default-active="$route.path"和router,开启路由;

3、需要跳转的菜单el-menu-item标签上index使用路由表示,如

            
      用户管理

4、菜单页使用做为每个页面的显示部分。      

二、固定菜单实例:

1、效果:访问系统判断是否已登录,未登录则跳转到登录页,已登录则进入中间页(额外插入的功能,测试navbar做导航),从中间页可以进入首页。

(1)登录页:

      VUE-Element组件(二)NavMenu导航菜单_第1张图片

(2)登录成功跳转到中间页:

VUE-Element组件(二)NavMenu导航菜单_第2张图片

(3)点击其他菜单试试:

   VUE-Element组件(二)NavMenu导航菜单_第3张图片

   VUE-Element组件(二)NavMenu导航菜单_第4张图片

(4)点击第一个菜单页里面的按钮“点击跳转”,这个才是我插入navbar测试页之前的主页,这里的菜单权限是从后台配置的:

    VUE-Element组件(二)NavMenu导航菜单_第5张图片

2、代码:

(1)route路由:

import Vue from 'vue'
import Router from 'vue-router'

Vue.use(Router)

/* Layout */
import Layout from '../views/layout/Layout'

export const constantRouterMap = [
  { path: '/404', component: () => import('@/views/404'), hidden: true },
  { path: '/login', component: () => import('@/views/login/index'), hidden: true },
  {
    path: '/midtest',
    name: 'midtest',
    hidden:true,
    component: () => import('@/views/midtest/index'),
    children: [
      {
        path: '/midtest',
        redirect: 'midtest1'
      },
     
      {
        path: '/midtest/midtest1',
        name: 'midtest1',
        component: () => import('@/views/midtest/midtest1')
      },
      {
        path: 'midtest2',
        name: 'midtest2',
        component: () => import('@/views/midtest/midtest2')
      },
      {
        path: 'midtest3',
        name: 'midtest3',
        component: () => import('@/views/midtest/midtest3')

      },
      {
        path: 'midtest41',
        name: 'midtest41',
        component: () => import('@/views/midtest/midtest4/midtest41')

      },
      {
        path: 'midtest42',
        name: 'midtest42',
        component: () => import('@/views/midtest/midtest4/midtest42')

      },
      {
        path: 'midtest51',
        name: 'midtest51',
        component: () => import('@/views/midtest/midtest5/midtest51')

      },
      {
        path: 'midtest521',
        name: 'midtest521',
        component: () => import('@/views/midtest/midtest5/midtest521')

      },
      {
        path: 'midtest522',
        name: 'midtest522',
        component: () => import('@/views/midtest/midtest5/midtest522')

      }
    ]
  },
  {
    path: '/',
    component: Layout,
    redirect: '/dashboard',
    name: '首页',
    icon: '首页',
    hidden: true,
    children: [{
      path: '/dashboard',
      component: () => import('@/views/dashboard/index')
    }]
  }
]
/**
* hidden: true                   if `hidden:true` will not show in the sidebar(default is false)
* alwaysShow: true               if set true, will always show the root menu, whatever its child routes length
*                                if not set alwaysShow, only more than one route under the children
*                                it will becomes nested mode, otherwise not show the root menu
* redirect: noredirect           if `redirect:noredirect` will no redirct in the breadcrumb
* name:'router-name'             the name is used by  (must set!!!)
* meta : {
    title: 'title'               the name show in submenu and breadcrumb (recommend set)
    icon: 'svg-name'             the icon show in the sidebar,
  }
**/
export const asyncRouterMap = [
  // { path: '/login', component: () => import('@/views/login/index'), hidden: true },
  {
    path: '/roleManage',
    redirct: '/roleManage/index',
    name: 'roleManage',
    component: Layout,
    meta: { title: '角色管理', authority: ['role_manage'] },
    noDropdown: true,
    children: [
      {
        path: 'index',
        name: 'index',
        component: () => import('@/views/roleManage/index'),
        meta: { title: '首页', authority: ['role_manage'], keepAlive: false }
      },
      {
        path: 'detail',
        name: 'detail',
        // hidden: true,
        component: () => import('@/views/roleManage/detail'),
        meta: { title: '详情', authority: ['role_manage'], keepAlive: false }
      }
    ]
  },
  //echarts
  {
    path: '/myecharts',
    redirct: '/myecharts/index',
    name: 'myecharts',
    component: Layout,
    meta: { title: 'myecharts', authority: ['role_manage'] },
    noDropdown: true,
    children: [
      {
        path: 'myecharts',
        name: 'myecharts',
        component: () => import('@/views/myecharts/index'),
        meta: { title: 'myecharts', authority: ['role_manage'], keepAlive: false }
      }
     
    ]
  },
  //watermark
  {
    path: '/watermark',
    redirct: '/watermark/index',
    name: 'watermark',
    component: Layout,
    meta: { title: 'watermark', authority: ['role_manage'] },
    noDropdown: true,
    children: [
      {
        path: 'watermark',
        name: 'watermark',
        component: () => import('@/views/watermark/index'),
        meta: { title: 'watermark', authority: ['role_manage'], keepAlive: false }
      }
     
    ]
  },
  //timer
  {
    path: '/timer',
    redirct: '/timer/index',
    name: 'timer',
    component: Layout,
    meta: { title: 'timer', authority: ['role_manage'] },
    noDropdown: true,
    children: [
      {
        path: 'timer',
        name: 'timer',
        component: () => import('@/views/timer/index'),
        meta: { title: 'timer', authority: ['role_manage'], keepAlive: false }
      }
     
    ]
  },
  //nav
  {
    path: '/navmenu/index',
    redirct: '/navmenu/index',
    name: 'navmenu',
    component: Layout,
    meta: { title: 'navmenu', authority: ['nav_manage'] },
    noDropdown: true,
    children: [
      {
        path: 'navmenu',
        name: 'navmenu',
        component: () => import('@/views/navmenu/index'),
        meta: { title: 'navmenu', authority: ['nav_manage'], keepAlive: false }
      },
      {
        path: '/navmenu/menu1',
        name: 'menu1',
        hidden:true,
        component: () => import('@/views/navmenu/menu1'),
        meta: { title: 'menu1', authority: ['nav_manage'], keepAlive: false }
      }
     
    ]
  },
  //分页查询
  {
    path: '/userPager',
    redirct: '/pager/userpager',
    name: 'userpager',
    component: Layout,
    meta: { title: '用户分页', authority: ['user_manage'] },
    noDropdown: true,
    children: [
      {
        path: 'index',
        name: 'index',
        component: () => import('@/views/pager/userpager'),
        meta: { title: '用户分页', authority: ['user_manage'], keepAlive: false }
      }
    ]
  },
  //select
  {
    path: '/select',
    redirct: '/select/index',
    name: 'select',
    component: Layout,
    meta: { title: 'select', authority: ['user_manage'] },
    noDropdown: true,
    children: [
      {
        path: 'index',
        name: 'index',
        component: () => import('@/views/select/index'),
        meta: { title: 'select', authority: ['user_manage'], keepAlive: false }
      },
      {
        path: 'user',
        name: 'user',
        component: () => import('@/views/select/user'),
        meta: { title: 'user', authority: ['user_manage'], keepAlive: false }
      },
      {
        path: 'tree',
        name: 'tree',
        component: () => import('@/views/select/tree'),
        meta: { title: 'tree', authority: ['user_manage'], keepAlive: false }
      },
      {
        path: 'treeselect',
        name: 'treeselect',
        component: () => import('@/views/select/treeselect'),
        meta: { title: 'treeselect', authority: ['user_manage'], keepAlive: false }
      }
    ]
  },
  //css
  {
    path: '/add',
    redirct: '/css/add',
    name: 'add',
    component: Layout,
    meta: { title: 'add', authority: ['user_manage'] },
    noDropdown: true,
    children: [
      
      {
        path: 'add1',
        name: 'add1',
        component: () => import('@/views/css/add1'),
        meta: { title: 'add1', authority: ['user_manage'], keepAlive: false }
      },

      {
        path: 'addmodel',
        name: 'addmodel',
        component: () => import('@/views/css/addmodel'),
        meta: { title: 'addmodel', authority: ['user_manage'], keepAlive: false }
      },
      {
        path: 'student',
        name: 'student',
        component: () => import('@/views/css/student'),
        meta: { title: 'student', authority: ['user_manage'], keepAlive: false }
      }
    ]
  },
 
]

export default new Router({
  // mode: 'history', // 后端支持可开
  scrollBehavior: () => ({ y: 0 }),
  routes: constantRouterMap
})

(2)权限拦截js:

import { asyncRouterMap, constantRouterMap } from '@/router/index'

/**
 * 通过meta.authority判断是否与当前用户权限匹配
 * @param authorities
 * @param route
 */
function hasPermission(authorities, route) {
  if (route.meta && route.meta.authority) {
    return authorities.some(authority => route.meta.authority.indexOf(authority) >= 0)
  } else {
    return true
  }
}

/**
 * 递归过滤异步路由表,返回符合用户角色权限的路由表
 * @param asyncRouterMap
 * @param authorities
 */
function filterAsyncRouter(asyncRouterMap, authorities) {
  const accessedRouters = asyncRouterMap.filter(route => {
    if (hasPermission(authorities, route)) {
      if (route.children && route.children.length) {
        route.children = filterAsyncRouter(route.children, authorities)
      }
      return true
    }
    return false
  })
  return accessedRouters
}

const permission = {
  state: {
    routers: constantRouterMap,
    addRouters: []
  },
  mutations: {
    SET_ROUTERS: (state, routers) => {
      state.addRouters = routers
      state.routers = constantRouterMap.concat(routers)
    }
  },
  actions: {
    GenerateRoutes({ commit }, data) {
      return new Promise(resolve => {
        const { authorities } = data
        let accessedRouters
        if (authorities.indexOf('admin') >= 0) {
          accessedRouters = asyncRouterMap
        } else {
          accessedRouters = filterAsyncRouter(asyncRouterMap, authorities)
        }
        commit('SET_ROUTERS', accessedRouters)
        resolve()
      })
    }
  }
}

export default permission

(3)login.vue:








(4)navbar菜单页:

VUE-Element组件(二)NavMenu导航菜单_第6张图片


(5)菜单页:随便看几个:




三、navbar菜单权限动态控制:上面的例子中,navbar的菜单权限是写死的,不同角色的用户登进来看到的菜单都是一样的,这里做下动态权限。

1、方法1:在router中控制权限:如现在给midtest2做权限控制:将整个Navbar的router放到asyncRouterMap下,并给midtest2的路由改为:

{
        path: 'midtest2',
        name: 'midtest2',
        meta: { title: 'midtest2', authority: ['role_manage'] },
        component: () => import('@/views/midtest/midtest2')
      }

这样如果某个用户没有role_manager的权限,点击midtest2会跳转到空白页,但是该用户还是可以看到midtest2的菜单导航。

2、方法2:给navbar菜单导航做权限控制:

(1)、数据库:

   配置11个菜单:

    VUE-Element组件(二)NavMenu导航菜单_第7张图片

    并给两个用户配置navbar菜单权限:

  VUE-Element组件(二)NavMenu导航菜单_第8张图片

(2)后端代码:

 @RequestMapping("/getNavMenu")
    private ResponseMessage getNavMenu(){
        JWTUserDTO jwtUser = (JWTUserDTO) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
        List menuDTOS = navMenuService.getNavMenu(jwtUser.getUserName());
        return ResponseMessage.success(menuDTOS);
    }
package com.demo.service.impl;

import com.demo.dao.NavMenuDao;
import com.demo.dto.NavMenuDTO;
import com.demo.service.NavMenuService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.List;

@Service("navMenuService")
public class NavMenuServiceImpl implements NavMenuService {

    @Autowired
    private NavMenuDao navMenuDao;

    @Override
    public List getNavMenu(String userAccount) {
        //一级菜单
        List navMenuDTOList = navMenuDao.getNavMenu(userAccount,0);
        //子菜单
        for(NavMenuDTO navMenuDTO : navMenuDTOList){
            //二级菜单
            Integer menuId = navMenuDTO.getId();
            List secondChildNavList = navMenuDao.getNavMenu(userAccount,menuId);
            navMenuDTO.setChildList(secondChildNavList);
            //三级菜单
            for(NavMenuDTO secondChild : secondChildNavList){
                Integer secondMenuId = secondChild.getId();
                List thirdChildNavList = navMenuDao.getNavMenu(userAccount,secondMenuId);
                secondChild.setChildList(thirdChildNavList);
            }
        }
        return navMenuDTOList;
    }
}




 

(3)前端代码:

登录成功后调用getNavMenu接口从后台获取navbar菜单列表,存储到store中,改造下上面例子中的index菜单页代码:




这里最多有三级菜单,如果菜单级别比较多,写在一个文件里比较复杂,可以封装成子组件调用,子组件里再调用组件自己,形成递归。 

看下效果:先是zhangsan登录:

VUE-Element组件(二)NavMenu导航菜单_第9张图片

再退出切换成lisi登录:

VUE-Element组件(二)NavMenu导航菜单_第10张图片

你可能感兴趣的:(VUE页面开发)