vue 多级菜单数据过滤?

el-menu实现无线多层级的菜单数据过滤,菜单显示与不显示是后台可配置的,根据一个定义好的状态字段来显示,status为0不显示,反之显示。

LeftMenuTree.vue组件:

<template>
    <div>
        <template v-for="(item, index) in this.menuData">
            <!-- 情况一:有子集的情况 -->
            <el-submenu :key="index" :index="String(index + 1)" v-if="item.children && item.children.length > 0">
                <template slot="title">
                    <i :class="[item.icon || 'el-icon-menu']" style="color: #000"></i>
                    <span slot="title" style="margin-left: 9px">{{item.menuName}}</span>
                </template>
                <left-menu-tree :menuData="item.children"></left-menu-tree>
            </el-submenu>
            <!-- 情况二:没子集的情况 -->
            <el-menu-item :key="index" v-else-if="item.menuStatus && item.menuStatus == 1" :index="String(index + 1)">
                <i :class="[item.icon || 'el-icon-menu']" style="color: #fff"></i>
                <span slot="title">{{item.menuName}}</span>
            </el-menu-item>
        </template>
    </div>
</template>

<script>
import { OPENTYPE } from "@/config/constant";
export default {
    props: ['menuData'],
    name: 'LeftMenuTree',
}
</script>

组件中使用:

<div class="left-menu">
  <el-menu
    active-text-color="#303133"
    class="el-menu-vertical-demo"
    text-color="#606266"
    @open="handleOpen"
    @close="handleClose"
  >
    <left-menu-tree :menuData="menuList"></left-menu-tree>
  </el-menu>
</div>

后端返回的数据结构如下:

const menuList= [
    {
        menuName: '菜单一',
        menuStatus: 1,
        children: [
            {
                menuName: 'ww',
                menuStatus: 0,
            },
            {
                menuName: 'rr',
                menuStatus: 1,
                children: [
                    {
                        menuName: 'tt',
                        status: 1,
                        children: [
                            {
                                menuName: 'ooo',
                                menuStatus: 0,
                            },
                            {
                                menuName: 'pp',
                                menuStatus: 1,
                                children: [
                                    {
                                        menuName: 'ooo',
                                        menuStatus: 0,
                                    },
                                    {
                                        menuName: 'pp',
                                        menuStatus: 0,
                                    },
                                ]
                            },
                        ]
                    },
                    {
                        menuName: 'rr',
                        menuStatus: 0,
                    },
                ]
            },
        ]
    },
    {
        menuName: '菜单二',
        menuStatus: 1,
        children: [
            {
                menuName: 'bb',
                menuStatus: 0,
            },
            {
                menuName: 'we',
                menuStatus: 0,
            },
        ]
    },
    {
        menuName: '菜单三',
        menuStatus: 1,
    }
]

这个时候就需要根据menuStatus状态值来显示,于是写了一个方法:

this.menuList.?.map(item => {
        return {
          ...item,
          children: item.children?.filter(item => item.menuStatus !== 0)
        }
      })
    }

但是过滤的不彻底,层级太多,就过滤不了,即使过滤了也还会显示菜单下拉项箭头。

image.png
求教大家对于层级太多的菜单怎么才能过滤出来menuStatus等于1的数据

阅读 2.7k
2 个回答
function filterMenuData(menuData) {
  return menuData
    .filter(item => item.menuStatus === 1) 
    .map(item => {
      if (item.children) {
        return {
          ...item,
          children: filterMenuData(item.children)
        };
      } else {
        return item;
      }
    });
}

this.menuList = filterMenuData(this.menuList);

首先,你这个方法写得略有问题,不能过滤深层次的,可以参考下面这一段递归:

const trees = [
    {
        label: 'l1',
        visiblity: true,
        children: [
            {
                label: 'l1-1',
                visiblity: true,
                children: [
                    {
                        label: 'l1-1-1',
                        visiblity: true,
                        children: [
                            {
                                label: 'l1-1-1-1',
                                visiblity: true,
                                children: [
                                    {
                                        label: 'l1-1-1-1-1',
                                        visiblity: true,
                                        children: [
                                            {
                                                label: 'l1-1-1-1-1-1',
                                                visiblity: false
                                            },
                                            {
                                                label: 'l1-1-1-1-1-2',
                                                visiblity: true
                                            }
                                        ]
                                    }
                                ]
                            }
                        ]
                    }
                ]
            }
        ]
    },
    {
        label: 'l2',
        visiblity: true,
        children: [
            {
                label: 'l2-1',
                visiblity: true,
                children: [
                    {
                        label: 'l2-1-1',
                        visiblity: true,
                        children: [
                            {
                                label: 'l2-1-1-1',
                                visiblity: false,
                                children: [
                                    {
                                        label: 'l2-1-1-1-1',
                                        visiblity: true,
                                        children: [
                                            {
                                                label: 'l2-1-1-1-1-1',
                                                visiblity: false
                                            },
                                            {
                                                label: 'l2-1-1-1-1-2',
                                                visiblity: true
                                            }
                                        ]
                                    }
                                ]
                            }
                        ]
                    }
                ]
            }
        ]
    }
];

type TTreeItem = {
    label: string;
    visiblity: boolean;
    children?: TTreeItem[];
};

function filterTrees(data: TTreeItem[]) {
    return data.filter(x => {
        if (x.children) {
            x.children = filterTrees(x.children);
            !x.children.length && delete x.children;
        }
        return !!x.visiblity;
    });
}


console.log(filterTrees(trees));

/*
[{"label":"l1","visiblity":true,"children":[{"label":"l1-1","visiblity":true,"children":[{"label":"l1-1-1","visiblity":true,"children":[{"label":"l1-1-1-1","visiblity":true,"children":[{"label":"l1-1-1-1-1","visiblity":true,"children":[{"label":"l1-1-1-1-1-2","visiblity":true}]}]}]}]}]},{"label":"l2","visiblity":true,"children":[{"label":"l2-1","visiblity":true,"children":[{"label":"l2-1-1","visiblity":true}]}]}]
*/

第二,可以与 web 协商,status 作为接口入参,想要什么数据,接口加层过滤更合适些

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题