基于Vue+elementUI menu组件的动态渲染多级目录

基于Vue+elementUI menu组件的动态渲染多级目录

需求描述

后端接口是,通过父级目录id查询子级目录列表,所以我需要动态渲染一个多级目录,目录深度不确定

后端返回数据参考

image-20231009205129836

比较关键的数据是

id 目录id

name 目录名字

level 目录所在层级

exitSon 是否有子层级

解决方法

我使用了elementUi的menu组件,因为项目是基于Vue2 的所有 是用的"element-ui": "2.15.10"

menu组件地址:https://element.eleme.cn/#/zh-CN/component/menu

具体代码

MultiLevelMenu组件

<template>
  <el-submenu v-if="isSubmenu" :index="computedIndex">
    <template slot="title">{{ item.fieldName }}</template>
    <MultiLevelMenu
      v-for="(subItem, subIndex) in item.submenu"
      :key="subIndex"
      :item="subItem"
      :index="computeChildIndex(subIndex)"
      :level="level + 1"
    />
  </el-submenu>
  <el-menu-item v-else :index="computedIndex">
    {{ item.fieldName }}
  </el-menu-item>
</template>

<script>
export default {
  name: "MultiLevelMenu",
  props: {
    item: Object,
    index: String,
    level: Number,
  },
  computed: {
      //判断是否有子级目录
    isSubmenu() {
      return Array.isArray(this.item.submenu);
    },
      //计算目录的index
    computedIndex() {
      if (this.level === 0) {
        return (this.index).toString();
      } else if (this.$parent && typeof this.$parent.computedIndex === 'string') {
        return `${this.$parent.computedIndex}-${this.index}`;
      } else {
        return (this.index).toString();
      }
    },
  },
  methods: {
      //计算目录的index
    computeChildIndex(subIndex) {
      if (this.level === 0) {
        return subIndex.toString();
      } else if (typeof this.computedIndex === 'string') {
        return `${this.computedIndex}-${subIndex}`;
      } else {
        return subIndex.toString();
      }
    },
  },
};
</script>

关于computeChildIndex函数和computedIndex函数,我把目录的路径存储在menu的index属性里面

比如index是1-3-3就代表是menu[1].children[3]..children[3] 第一层第一个–>第二层的第三个–>第三层的第三个

其实可以不使用这样的方式存储menu的路径,elementUI官方提供相应的方法

image-20231009210132438

indexPath是一个数组,如上1-3-3,它会自动存储 [1,3,3]当时作者使用1-3-3方式是因为menu组件抽风了,就是没有存储到路径。。。。

然后怎么在父组件中使用MultiLevelMenu

<el-menu :default-active="activeMenuIndex" 
         mode="vertical"
         @open="handleMenuOpen"
         @select="handleItemSel"
         unique-opened
>
  <MultiLevelMenu
    v-for="(item, index) in menu"
    :key="index"
    :item="item"
    :index="String(index)"
    :level="item.level"
  />
</el-menu>

el-menu相关属性可以查询官网解释,此处简单解释一下

:default-active="activeMenuIndex" 当前激活菜单的index String类型
mode=“vertical” 模式 vertical表示垂直显示
@open=“handleMenuOpen” 目录展开事件
@select=“handleItemSel” 子叶目录选中事件
unique-opened 是否只保持一个子菜单的展开

<MultiLevelMenu
    v-for="(item, index) in menu"//循环相关 menu表示你的目录列表 Array类型
    :key="index"//循环相关
    :item="item"//当前项
    :index="String(index)"//index
    :level="item.level"//层级
  />

其他相关实现

父组件script部分,仅供参考。

<script>
  export default {
      data(){
        return{
            //当前激活菜单的index
            activeMenuIndex: '1',
            //目录
            menu:[],  
          }
      },
       created() {
           //第一次加载目录
           this.getMenuTopList();
       },
      methods: {
        //目录展开事件
          handleMenuOpen(index, indexPath) {
              console.log(index, indexPath);
              //1.使用index(1-3-3方式)
               let currentMenu=this.getCurrentMenu(index);
              //发送请求
              //请求成功之后更新数据
              const submenu=res.data//可能需要对请求成功的数据做一些转换 
               this.$set(currentMenu,'submenu',submenu)
              //2.使用indexPath([1,3,3]方式)
               let currentMenu=null;
               for (let i=0;i<indexPath.length;i++){
                 if (i===0){
                   currentMenu=this.menu[arr[i]]
                 }else {
                   if (currentMenu&&currentMenu.submenu&&currentMenu.submenu.length>0){
                     currentMenu=currentMenu.submenu[arr[i]]
                   }
                 }
               }
               //发送请求
              //请求成功之后更新数据
              const submenu=res.data//可能需要对请求成功的数据做一些转换 
               this.$set(currentMenu,'submenu',submenu)
    	   }
          },
        //子叶目录点击事件
          handleItemSel(index, indexPath) {
              console.log(index, indexPath);
          },
          //第一次加载目录
          getMenuTopList(){
              //向后端发送请求
              this.menu=res.data//可能需要对请求成功的数据做一些转换 
          },
          // 根据index路径获取当前的目录对象
    	 getCurrentMenu(index){
    	   const arr = index.split('-').map(Number);
    	   let currentMenu=null;
    	   for (let i=0;i<arr.length;i++){
    	     if (i===0){
    	       currentMenu=this.menu[arr[i]]
    	     }else {
    	       if (currentMenu&&currentMenu.submenu&&currentMenu.submenu.length>0){
    	         currentMenu=currentMenu.submenu[arr[i]]
    	       }
    	     }
    	   }
    	   return currentMenu;
    	 },
    }
  }
</script>

实战代码参考

下图是作者的实际项目的代码,仅供参考

image-20231009212511500

image-20231009212535572

image-20231009212653904

data部分

image-20231009212729434

本文由博客一文多发平台 OpenWrite 发布!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
渲染多级菜单,可以使用 Element UI 的 Menu 组件Submenu 组件。首先,你需要定义一个菜单数据源,包含多级菜单的信息。例如: ```javascript menuData: [ { name: 'Dashboard', icon: 'el-icon-s-home', children: [ { name: 'Dashboard 1', path: '/dashboard/1' }, { name: 'Dashboard 2', path: '/dashboard/2' } ] }, { name: 'Products', icon: 'el-icon-menu', children: [ { name: 'Product 1', path: '/product/1' }, { name: 'Product 2', path: '/product/2', children: [ { name: 'Sub Product 1', path: '/product/2/sub/1' }, { name: 'Sub Product 2', path: '/product/2/sub/2' } ] } ] } ] ``` 然后,在你的侧边栏组件中,使用 MenuSubmenu 组件渲染菜单: ```html <el-menu :default-active="$route.path" class="el-menu-vertical-demo" @open="handleOpen" @close="handleClose"> <template v-for="item in menuData"> <el-submenu v-if="item.children" :index="item.name"> <template slot="title"> <i :class="item.icon"></i> <span slot="title">{{ item.name }}</span> </template> <el-menu-item-group> <template v-for="child in item.children"> <el-menu-item :index="child.path">{{ child.name }}</el-menu-item> <el-submenu v-if="child.children" :index="child.path"> <template slot="title">{{ child.name }}</template> <el-menu-item-group> <template v-for="subChild in child.children"> <el-menu-item :index="subChild.path">{{ subChild.name }}</el-menu-item> </template> </el-menu-item-group> </el-submenu> </template> </el-menu-item-group> </el-submenu> <el-menu-item v-else :index="item.path"> <i :class="item.icon"></i> <span slot="title">{{ item.name }}</span> </el-menu-item> </template> </el-menu> ``` 这样,就可以渲染多级菜单了。注意,在模板中使用了 v-for 来遍历菜单数据源,并使用 v-if 判断是否存在子菜单。如果存在子菜单,则使用 el-submenu 组件渲染。如果还存在子菜单,则继续使用 el-submenu 组件递归渲染

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值