vue+springboot实现动态加载菜单栏

实现思路:数据库中有菜单表,角色表,用户表,角色和用户映射的表,菜单和角色映射的表五个表,springboot利用jpa操作数据库,提供vue前端获取这些表中的数据,vue前端利用懒加载,对当前登录的用户的角色所拥有的菜单栏进行显示和渲染。
本文参考Evan-Nightly写的"Vue + Spring Boot 项目实战"系列的文章,他那个系列教程写得很棒,我吹爆。后期进阶的部分详细步骤这位老哥没放出来,我这里稍微总结一下,方便基础不好的老哥,也算是给自己查漏补缺。
具体实现:
首先来看菜单表的内容:
vue+springboot实现动态加载菜单栏_第1张图片
这里跳过springboot的操作直接看前端的部分会方便理解一点,我们用vuex存储菜单表的数据,在store/index.js里面定义菜单表的变量,以及该变量的set方法,如下图所示。
vue+springboot实现动态加载菜单栏_第2张图片
这样前端姑且就有了存储每个用户对应角色的菜单数据变量了。接下来看看这个变量从哪被赋值以及具体的数据结构。
前端vue有个router控制路径的跳转,router有个自带的beforeEach方法,在这里面写函数,可以实现一些在路径跳转前的验证逻辑,这些方法都在main.js里写,这里的任务是发送请求给后端,得到菜单栏的数据,然后转一下格式,再调用上面store/index.js定义的set方法,把菜单数据存到前端上去。
在main.js里面写函数,上面的是发请求,下面的是转格式:

const initAdminMenu = (router, store) => {
  // 防止重复触发加载菜单操作
  if (store.state.adminMenus.length > 0) {
    return
  }
  Axios.get('http://127.0.0.1:8088/api/menu').then(resp => {
    if (resp && resp.status === 200) {
      //console.log(resp.data.result)
      //console.log(resp.data)
      var fmtRoutes = formatRoutes(resp.data)

      console.log("initmenu......")
      console.log(fmtRoutes)
      router.addRoutes(fmtRoutes)
      store.commit('initAdminMenu', fmtRoutes)
    }
  })
}
//转格式
const formatRoutes = (routes) => {
  let fmtRoutes = []
  console.log("=====origin data=====")
  console.log(routes)
  console.log("=====origin data=====")
  routes.forEach(route => {
    if (route.children) {
      route.children = formatRoutes(route.children)
    }

    let fmtRoute = {
      path: route.path,
      component: resolve => {
        require(['./components/admin/' + route.component + '.vue'], resolve)
      },
      name: route.name,
      nameZh: route.namezh,
      iconCls: route.iconcls,
      meta: {
        requireAuth: true
      },
      children: route.children
    }
    fmtRoutes.push(fmtRoute)
  })
  console.log("=====processed data=====")
  console.log(fmtRoutes)
  console.log("=====processed data=====")
  return fmtRoutes
}

在beforeEach中调用:

    if (store.state.user && to.path.startsWith('/admin')) {
      //console.log("first login,initmenu......")
      initAdminMenu(router, store)
    }

这时候我们已经实现了完整的数据的存储,接下来去写界面,显示渲染这些数据。编写vue文件:AdminMenu,这里面把上面得到的数据作为成员变量,用v-for,循环渲染,具体细节如下。

<template>
  <el-menu
    :default-active="currentPath"
    class="el-menu-admin"
    router
    mode="vertical"


    :collapse="isCollapse">
    <div style="height: 80px;"></div>
    <!--index 没有用但是必需字段-->
    <el-submenu  v-for="(item,i) in adminMenus" :key="i" :index="(i).toString()" style="text-align: left">
        <span slot="title" style="font-size: 17px;">
          <i :class="item.iconCls"></i>
          {{item.nameZh}}
        </span>
      <el-menu-item v-for="child in item.children" :key="child.path" :index="child.path">
        <i :class="child.icon"></i>
        {{ child.nameZh }}
      </el-menu-item>
    </el-submenu>
  </el-menu>
</template>

<script>
    export default {
        name: "AdminMenu",
      data () {
        return {
          isCollapse: false
        }
      },
      computed: {
        adminMenus () {
          return this.$store.state.adminMenus
        },
        currentPath () {
          return this.$route.path
        }
      }
    }

</script>

<style scoped>
  .el-menu-admin {
    border-radius: 5px;
    height: 100%;
  }
</style>

这个AdminMenu其实是个小部件,还有个Header小部件,被组装在一起放在AdminIndex.vue里面。
在这里开始仔细分析一下上面数据库菜单表里面的结构,表里component这个字段对应前端中的component,有user/Role,这种就是在user文件夹下的Role.vue组件,为了加快开发速度,可以按着这些值,先做出这些文件夹和组件,组件就显示该组件的名字比如这样:
vue+springboot实现动态加载菜单栏_第3张图片
我还找了个权限最低的角色,只需要显示以下几个组件。
vue+springboot实现动态加载菜单栏_第4张图片
记得要在router/index.js里添加主/admin路径,指向AdminIndex.vue
其他组件的路径不用特地配置,刚才那个渲染神奇得把这些路径的配置解决掉了。我的配置大概是这样的。
vue+springboot实现动态加载菜单栏_第5张图片
到这里前端和数据的交互基本已经完成,剩下的就是后端接口问题了。
流程:连接数据库,写pojo类,写dao接口,写service类,写controller类……,这个没啥特别要提的,就是根据当前登录账号的用户找到他的角色,再找到他的菜单,根据找到的菜单,去看那位男人的git代码就好,强烈建议写完一个类/接口编译一次,有时候错误出在dao层,pojo层,坑得很……
在把后端接口和前端整合在一起签,先测试一下接口是否正确:首先发送登录的请求,记得设置rememberMe为true,接着发请求菜单的请求,返回到的应该是json数组如下图所示:
vue+springboot实现动态加载菜单栏_第6张图片

最后嘚瑟一下我自己的运行成果截图:
vue+springboot实现动态加载菜单栏_第7张图片

你可能感兴趣的:(vue+springboot实现动态加载菜单栏)