问题形容

在后盾治理我的项目中,牵涉到权限的货色少数是后端传递过去的数据,前端去展现(当然前端也会做一些管制)。就导航菜单而言,也不能写死了,须要在用户登录了当前,发申请获取用户的对应菜单数据,依据对应的数据去展现对应的菜单。
本文记录一下应用组件递归的形式,封装一个动静的、多级的导航菜单,从而实现动态效果。

看这篇文章之前,能够看看我之前的《vue组件的递归自调用~代码思路剖析》文章,本篇文章是之前文章的延长。地址如下:https://segmentfault.com/a/11...

效果图

咱们先看一下效果图:

思路剖析

  • 首先,咱们要和后端沟通返回的数据格式,咱们晓得前端的el-menu菜单的外围数据属性有四个:

    • 菜单的名字name
    • 点击菜单进行路由跳转的门路path
    • 菜单上小图标icon
    • 菜单是不是最内层的菜单,即children是否是空数组,当children为空的时候,就阐明到菜单最里层了。(最里层的菜单children为空数组的时候,点击的时候,做路由跳转)
  • 所以须要有name、path、icon、children属性,且得是一个树结构的格局,和左侧导航菜单保持一致。
  • 这里咱们模仿一下后端返回的代码

后端返回的el-menu菜单数据

menuArr: [    {// 留神!留神!有children的菜单项,path不会应用的,所以path为什么都无所谓;没children的,即children的length等于0的,才会应用path属性做路由跳转      name: "前端三大框架",      path: "前端三大框架",       icon: "el-icon-star-off",      children: [        {          name: "vue页面",          path: "/vue",          icon: "el-icon-star-off",          children: [],        },        {          name: "react页面",          path: "/react",          icon: "el-icon-star-off",          children: [],        },        {          name: "angular页面",          path: "/angular",          icon: "el-icon-star-off",          children: [],        },      ],    },    {      name: "后端两大框架",      path: "后端两大框架",      icon: "el-icon-star-off",      children: [        {          name: "Spring Boot页面",          path: "/springBoot",          icon: "el-icon-star-off",          children: [],        },        {          name: "Spring页面",          path: "Spring页面",           icon: "el-icon-star-off",          children: [            {              name: "MySql页面",              path: "/mysql",              icon: "el-icon-star-off",              children: [],            },            {              name: "Redis页面",              path: "/redis",              icon: "el-icon-star-off",              children: [],            },          ],        },        {          name: "Mybatis页面",          path: "/mybatis",          icon: "el-icon-star-off",          children: [],        },      ],    },  ]
咱们先看一下非动静多级菜单的写法,而后再看一下递归组件动静多级菜单的写法

非动静多级菜单(写死了,不灵便,不倡议应用)

<el-menu  :default-active="activeIndex"  class="elMenu"  background-color="#333"  text-color="#B0B0B2"  active-text-color="#fff"  :unique-opened="true"  router  ref="elMenu"  @select="menuSelect">  <el-submenu index="非叶子节点也须要index属性">    <template slot="title">      <i class="el-icon-star-off"></i>      <span>前端三大框架</span>    </template>    <!-- 这个是没子节点的 没有子内容,用el-menu-item构造 -->    <el-menu-item index="/vue">      <i class="el-icon-star-off"></i>      <span slot="title">vue页面</span>    </el-menu-item>    <el-menu-item index="/react">      <i class="el-icon-star-off"></i>      <span slot="title">react页面</span>    </el-menu-item>    <el-menu-item index="/angular">      <i class="el-icon-pear"></i>      <span slot="title">angular页面</span>    </el-menu-item>  </el-submenu>    <el-submenu index="非叶子节点也须要index属性哦">    <template slot="title">      <i class="el-icon-star-off"></i>      <span>后端两大框架</span>    </template>    <el-menu-item index="/springBoot">      <i class="el-icon-star-off"></i>      <span slot="title">Spring Boot页面</span>    </el-menu-item>      <!-- 留神看这里有子节点的无子节点的html标签的区别 -->      <!-- 这个是有子节点的 还有子内容,用el-submenu构造-->      <el-submenu index="非叶子节点也须要index属性哈">          <template slot="title">            <i class="el-icon-star-off"></i>            <span>Spring页面</span>          </template>          <el-menu-item index="/mysql">            <i class="el-icon-star-off"></i>            <span slot="title">MySql页面</span>          </el-menu-item>          <el-menu-item index="/redis">            <i class="el-icon-star-off"></i>            <span slot="title">Redis页面</span>          </el-menu-item>      </el-submenu>      <!-- 这个是没子节点的 没有子内容,用el-menu-item构造 -->      <el-menu-item index="/mybatis">          <i class="el-icon-star-off"></i>          <span slot="title">Mybatis页面</span>      </el-menu-item>  </el-submenu></el-menu>

发现法则

通过上述代码,咱们发现,el-menu代码大抵分为两类,有子集和没有子集的

  • 有子集用的是el-submenu标签包template标签指定名字跟很多个el-menu-item标签
  • 没子集间接用很多个el-menu-item标签

得出上述法则,咱们就能应用递归组件形式去封装一个动静菜单

动静菜单代码

外层菜单局部

html局部

<el-menu  :default-active="activeIndex"  class="elMenu"  background-color="#333"  text-color="#B0B0B2"  active-text-color="#fff"  :unique-opened="true"  router  ref="elMenu"  @select="menuSelect">  <!-- 递归动静菜单 -->  <myitem :data="menuArr"></myitem></el-menu>

js局部

import myitem from "./components/myitem.vue"; // 引入递归菜单组件export default {  name: "Home",  components: {    myitem, // 注册一下  },  data() {    return {      activeIndex: this.$route.path,      menuArr: [...] // 数据是上述咱们模仿的数据,#后端返回的el-menu菜单数据#    };  }};

内层递归菜单项局部

<template>  <div>    <template v-for="(item, index) in data">      <!-- 因为有子集和无子集渲染html标签不一样,所以要分为两种状况           状况一:有子集的状况:                         -->      <el-submenu        :key="index"        :index="item.path"        v-if="item.children.length > 0"      >        <template slot="title">          <i :class="item.icon"></i>          <span>{{ item.name }}</span>        </template>        <myitem :data="item.children"></myitem>      </el-submenu>      <!-- 状况二:没子集的状况: -->      <el-menu-item :key="index" v-else :index="item.path">        <i :class="item.icon"></i>        <span slot="title">{{ item.name }}</span>      </el-menu-item>    </template>  </div></template><script>export default {  name: "myitem",  props: {    data: {      type: Array,      default: [],    },  },  // 留神: 在template标签上应用v-for,:key="index"不能写在template标签上,因为其标签不会被渲染,会引起循环谬误};</script>

残缺代码

残缺代码我上传到Gitee下来了,欢送大家下载查看,这样更加不便了解。
地址:https://gitee.com/ah-shuai/dy...