vue如何从后台获取数据生成动态菜单列表

目录
  • 1.数据准备
  • 2.选择组件
  • 3.配置路由
  • 4.不出问题这样就可以实现动态路由了
  • 5.完整代码

1.数据准备

树形菜单基本数据很简单,只需要菜单id,菜单名称,路由地址,图标。下图中的节点id和父节点id是为了后端生成树形数据,只负责前端的话只需要拿到前面说的四个数据就行。

后端将数据转成树形结构,传给前端的数据结构如图

2.选择组件

我直接用element-ui的el-menu组件,结构是(这是用来注释的,完整代码在后面)

    <el-menu>
      <template v-for="(item, key) in menuList">-----前端得到的数据存放到menuList数组
        <el-submenu :key="key" v-if="item.children && item.children.length!==0" :index="item.m_url">----父级菜单,判断有子节点,index是路由跳转
          <template slot="title">----插槽
            <i :class="item.m_icon"></i>-----图标
            <span>{{ item.m_name }}</span>----菜单名称
          </template>
          <el-menu-item v-for="(val, index) in item.children" :index="val.m_url" :key="index">----二级菜单
            <template slot="title">
              <i :class="val.m_icon"></i>
              <span>{{ val.m_name }}</span>
            </template>
          </el-menu-item>
        </el-submenu>
        <el-submenu v-else :key="item.m_n_id" :index="item.m_url">没有子节点
          <template slot="title">
            <i :class="item.m_icon"></i>
            <span>{{ item.m_name }}</span>
          </template>
        </el-submenu>
      </template>
    </el-menu>

3.配置路由

跳转到那个页面是由写在router目录下的index.js的component指定的

import Vue from 'vue'
import Router from 'vue-router'
Vue.use(Router)
export default new Router({
  // mode: 'history',
  routes: [
    {
      path: '/',
      name: 'home',
      meta: {
        key: '1'
      },
      component: () => import("@/views/home"),
      children: [{
        path: '/courseApplication', // 这个路径必须与后端传回数据的m_url字段相对应
        name: 'courseApplication',
        meta: {
          key: '1-1'
        },
        component: () => import('@/views/trainManage/courseApplication') // 要跳转的页面路径
      }]
    }
  ]
})

4.不出问题这样就可以实现动态路由了

5.完整代码

menu.vue

<template>
  <div class="menu">
     <el-menu
      class="el-menu-vertical-demo"
      @open="handleOpen"
      @close="handleClose"
      background-color="rgb(255,255,255)"
      text-color="rgb(28,41,89)"
      router = router
      active-text-color="rgb(28,41,89)">
      <template v-for="(item, key) in menuList">
        <el-submenu :key="key" v-if="item.children && item.children.length!==0" :index="item.m_url">
          <template slot="title">
            <i :class="item.m_icon"></i>
            <span>{{ item.m_name }}</span>
          </template>
          <el-menu-item v-for="(val, index) in item.children" :index="val.m_url" :key="index">
            <template slot="title">
              <i :class="val.m_icon"></i>
              <span>{{ val.m_name }}</span>
            </template>
          </el-menu-item>
        </el-submenu>
        <el-submenu v-else :key="item.m_n_id" :index="item.m_url">
          <template slot="title">
            <i :class="item.m_icon"></i>
            <span>{{ item.m_name }}</span>
          </template>
        </el-submenu>
      </template>
    </el-menu>
  </div>
</template>
<script>
import { mapActions } from 'vuex';
  export default {
    name: "asideItem",
    data(){
      return{
        router: true,
        isCollapse: true,
        label: false,
        menuList: []
      }
    },
    mounted() {
      this.getMenu()
    },
    methods: {
      ...mapActions([
        'getMenuList'
      ]),
      handleOpen(key, keyPath) {
        console.log(key, keyPath);
      },
      handleClose(key, keyPath) {
        console.log(key, keyPath);
      },
      labelChange: function() {
        console.log(this.label);
      },
      getMenu: function() { // 从后台获取菜单列表
        this.getMenuList().then(res => {
          if(res.errno === 0) {
            this.menuList = res.data
          } else {
            this.$message.error(res.data)
          }
        }).catch(error => { this.$message.error(error) })
      }
    }
  };
</script>
<style lang="postcss" scoped>
  .menu {
    transition: width 0.28s ease-out;
    width: 180px;
    background: rgb(255, 255, 255);
    height: calc(100vh - 46px);
    & .el-menu{
      width: 100%;
      border-right: none;
    }
    & :hover {
    }    
  }
  
</style>
<style>
.el-menu-item:hover{
  outline: 0 !important;
  background-color: rgb(232,240,255)!important;
}
.el-menu-item.is-active {
  background: rgb(210,226,255) !important;
}
.el-submenu__title:focus, .el-submenu__title:hover{
  outline: 0 !important;
  background: none !important;
}
</style>

router 下的index.js根据具体数据进行配置

import Vue from 'vue'
import Router from 'vue-router'
Vue.use(Router)
export default new Router({
  // mode: 'history',
  routes: [
    {
      path: '/',
      name: 'home',
      meta: {
        key: '1'
      },
      component: () => import("@/views/home"),
      children: [{
        path: '/courseApplication', // 这个路径必须与后端传回数据的m_url字段相对应
        name: 'courseApplication',
        meta: {
          key: '1-1'
        },
        component: () => import('@/views/trainManage/courseApplication') // 要跳转的页面路径
      }]
    }
  ]
})

-----------------------这是分割线(以下是修改前的)-----------------------

将目录作为子目录添加到首页下面,可以显示出来,但是第二次点击同一个菜单时,会出现

地址叠加的情况,导致页面不能显示。而且先点击到别的页面也会出现这种情况

解决办法:在获取动态列表的时候,数据里面有url和source,不要去获取source,内层外层循环都获取url,然后在router/index 里面,path改为跟获取的url一样的内容

这个path主要是为了匹配菜单,最终调取页面是由component完成的。

刚开始的时候还有一个问题:

就是点击菜单栏的某一项,会全屏显示某一个页面,而不是懒加载的方式,只显示在中间部分,解决办法是将获取的路由放在跟路由下面,作为子组件呈现出来

完整代码

<el-menu
          :default-active="this.$route.path"
          class="el-menu-vertical"
          router
          :collapse="iscollapse"
          :collapse-transition="false"
          :active-text-color="variables.menuActiveText"
          :background-color="variables.menuBg"
          :text-color="variables.menuText"
        >
          <fragment>
            <template v-for="item in menuList">
              <fragment v-if="item != null" :key="item.url">
                <el-submenu v-if="item.childMenuInfoTreeSet && item.childMenuInfoTreeSet.length > 0" :key="item.url" :index="item.url.toString()">
                  <template slot="title">
                    <i :class="item.iconcls.toString()" class="iconSize" />
                    <span slot="title">{{ item.menuName }}</span>
                  </template>
                  <el-menu-item v-for="val in item.childMenuInfoTreeSet" :key="val.title" :index="val.url.toString()">
                    <i :class="val.iconcls.toString()" class="iconSize" />
                    <span slot="title">{{ val.menuName }}</span>
                  </el-menu-item>
                </el-submenu>
                <el-menu-item v-else :key="item.url" :index="item.url.toString()">
                  <i :class="item.iconcls" class="iconSize" />
                  <span slot="title">{{ item.menuName }}</span>
                </el-menu-item>
              </fragment>
            </template>
          </fragment>
        </el-menu>

以上为个人经验,希望能给大家一个参考,也希望大家多多支持我们。

(0)

相关推荐

  • vue侧边栏动态生成下级菜单的方法

    循环传入的数据去生成下级菜单 <template> <div class="headBar"> <div class="title"> 微商城管理后台 </div> <el-menu class="el-menu-headBar" mode="horizontal" @select="handleSelect" background-color=&quo

  • Vue 动态添加路由及生成菜单的方法示例

    写后台管理系统,估计有不少人遇过这样的需求:根据后台数据动态添加路由和菜单. 为什么这么做呢?因为不同的用户有不同的权限,能访问的页面是不一样的. 在网上找了好多资料,终于想到了解决办法. 动态生成路由 利用 vue-router 的 addRoutes 方法可以动态添加路由. 先看一下官方介绍: router.addRoutes router.addRoutes(routes: Array<RouteConfig>) 动态添加更多的路由规则.参数必须是一个符合 routes 选项要求的数组.

  • 使用vue-element-admin框架从后端动态获取菜单功能的实现

    2.详解 ​整体思路为:登陆 > 成功后根据用户信息获取菜单 > 根据菜单生成路由信息 2.1.新增asyncRoutes路由 ​在vue-router路径src\router\index.js中新增asyncRoutes数组,用来存放后端获取的菜单对应的路由信息. export const asyncRoutes = [ { path: '*', redirect: '/404', hidden: true } ] constantRoutes和asyncRoutes的区别 constant

  • vue-router 基于后端permissions动态生成导航菜单的示例代码

    目录 Vue.js 1.注册全局守卫 2.Vuex状态管理 全局缓存routes 3.路由拦截 4.路由菜单 5.递归菜单vue组件 Vue.js vue-router vuex 1.注册全局守卫 核心逻辑 1.token身份验证(后端) => token失效返回登录页面 2.获取用户权限 3.校验permissions,动态添加路由菜单 router.beforeResolve 注册一个全局守卫.和 router.beforeEach 类似,区别是在导航被确认之前,同时在所有组件内守卫和异步路

  • vue如何从后台获取数据生成动态菜单列表

    目录 1.数据准备 2.选择组件 3.配置路由 4.不出问题这样就可以实现动态路由了 5.完整代码 1.数据准备 树形菜单基本数据很简单,只需要菜单id,菜单名称,路由地址,图标.下图中的节点id和父节点id是为了后端生成树形数据,只负责前端的话只需要拿到前面说的四个数据就行. 后端将数据转成树形结构,传给前端的数据结构如图 2.选择组件 我直接用element-ui的el-menu组件,结构是(这是用来注释的,完整代码在后面) <el-menu> <template v-for=&qu

  • Vue+Element ui 根据后台返回数据设置动态表头操作

    由于后端是多人开发,也没有规范数据格式,所有页面是我一个人开发,所以就会遇到同样的页面不同的返回数据格式问题. 一.根据element文档,利用prop属性绑定对应值,label绑定表头. html <el-table class="tb-edit" highlight-current-row :data="tableData" border style="width: 100%"> <template v-for="

  • vue.js配合$.post从后台获取数据简单demo分享

    首先导入 <script type="text/javascript" src="/island/stage/js/vue.min.js"></script> html样式: <div id="main-content" class="wrap-container zerogrid"> <article id="news_content" v-for="i

  • vue+vuex+axios从后台获取数据存入vuex,组件之间共享数据操作

    在vue项目中组件间相互传值或者后台获取的数据需要供多个组件使用的情况很多的话,有必要考虑引入vuex来管理这些凌乱的状态,今天这边博文用来记录这一整个的过程,后台api接口是使用webpack-server模拟的接口,这个前面的文章中有提到,需要的可以去翻阅. 整个的流程是在组件的created中提交dispatch,然后通过action调用一个封装好的axios然后再触发mutation来提交状态改变state中的数据,然后在组件的计算属性中获取state的数据并渲染在页面上 首先新需要在项

  • vue解决使用$http获取数据时报错的问题

    在引用vue作为一个插件时,使用$http获取数据时报错 Failed to load http://****/ajaxGrainRain: Request header field Content-Type is not allowed by Access-Control-Allow-Headers in preflight response. 只需在后台加上 add_header 'Access-Control-Allow-Headers' 'DNT, X-CustomHeader,Keep

  • vue 绑定对象,数组之数据无法动态渲染案例详解

    项目场景: 黑马vue项目管理实战,获取商品分类,展开栏的标签页中修改修改数据属性 问题描述: 在本该点击+new tag这个标签页时弹出一个input框让用户输入需要添加的属性 结果点击时却不能立马渲染 async getParametersList() { this.cat_id = this.currentSelect[this.currentSelect.length - 1]; const { data: res } = await this.$http.get( `categorie

  • Vue.js如何利用v-for循环生成动态标签

    目录 前言 一.当写入数据为数组时 二.当写入数据为对象时 三.作用于标签属性和事件 总结 前言 使用v-for可以用于动态生成html标签.其实就是对于vue中属性是对象或者数组进行遍历生成新的标签. v-for就像java中的for循环一样,迭代需要的所有元素. 大多数情况是以一个数组嵌套多个对象的数据进行v-for循环 一.当写入数据为数组时 如果循环遍历得到的value值是一个对象,需要使用里面的值可以用 对象名.key 来调用key对应的value值 v-for写入数组的格式: arr

  • DataTables+BootStrap组合使用Ajax来获取数据并且动态加载dom的方法(排序,过滤,分页等)

    Datatables是一款jquery表格插件.它是一个高度灵活的工具,可以将任何HTML表格添加高级的交互功能. 主要功能 分页,即时搜索和排序 几乎支持任何数据源:DOM, javascript, Ajax 和 服务器处理 支持不同主题 DataTables, jQuery UI, Bootstrap, Foundation 各式各样的扩展: Editor, TableTools, FixedColumns -- 丰富多样的option和强大的API 支持国际化 超过2900+个单元测试 免

  • JQuery通过后台获取数据遍历到前台的方法

    做项目中,经常会通过调用后台接口把数据显示到前台页面上来,之前遇到过的问题是,前台页面是用ul+li标签写的,在调用接口调试时发现返回的数据有很多组的,而在前台显示的时候只有一条数据,毋容置疑,一定是遍历时出现了问题,下面来简单分析下. 前台代码: 案例1: <div class="Record"> <div class="RecordLeft text-center fl"> <p><span>经办记录</sp

  • 详解vue渲染从后台获取的json数据

    公司项目原来用的框架扩展性太差,准备更新前台页面然后用vue渲染dom 然后我写了一个demo $(document).ready(function(){ $.ajax({ type:"post", url:"", async:true, data:{ }, dataType:"json", success:function(data){ var a=new Vue({ el:"#detail-info-id", data:

随机推荐