Vue:Elemenu-Plus递归型菜单组件封装

        前端开发中,经常遇到需要与后端配置,前端动态渲染菜单的应用场景,而究其本质,就是菜单组件的应用,只是在不确定菜单级数的情况下,我们需要对组件做一个递归处理,让它能够适应大多数应用场景。

递归型菜单举例

         如上图所示,以Element-Plus组件库为例,对于一个递归型菜单,我们该如何进行封装呢?先假设后端接口返回的简单菜单信息如下,

[
            {
                index: "1",
                path: "/index",
                routeParams: {},
                meta: {
                    title: "首页",
                    icon: "House",
                }
            },
            {
                index: "2",
                path: "/funcs",
                routeParams: {},
                meta: {
                    title: "功能中心",
                    icon: "Menu",
                }
            },
            {
                index: "3",
                path: "/cases",
                routeParams: {},
                meta: {
                    title: "项目案例",
                    icon: "Grid",
                    mode:"vertical",
                },
                children: [
                    {
                        index: "3-1",
                        path: "",
                        routeParams: {},
                        meta: {
                            title: "item one",
                            icon: "Orange",
                        },
                        children:[
                            {
                                index: "3-1-1",
                                path: "",
                                routeParams: {},
                                meta: {
                                    title: "item one-one",
                                    icon: "Orange",
                                },
                            }
                        ]
                    },
                    {
                        index: "3-2",
                        path: "",
                        routeParams: {},
                        meta: {
                            title: "item two",
                            icon: "Orange",
                        }
                    },
                    {
                        index: "3-3",
                        path: "",
                        routeParams: {},
                        meta: {
                            title: "item three",
                            icon: "Orange",
                        }
                    }
                ]
            }
        ]

        实际开发中,还可能包括组件路径、菜单项显隐等相关字段信息,此处暂不考虑,我们当前的核心需求是:如何去完成这样的一个菜单组件的封装。

        对于上图所示的效果,我在此处所做的组件封装示例代码如下,

<!-- 多级菜单组件抽取 -->
<template>
    <el-menu :default-active="activeIndex" :class="customMenuClass" background-color="transparent" text-color="#fff"
        active-text-color="#ffef40" :mode="mode" @select="handleSelect" :ellipsis="false">
        <template v-for="(item) in items">
            <template v-if="item.children">
                <el-sub-menu :index="item.index" popper-class="el-sub-menu-popper-class">
                    <template #title>
                        <router-link :to="item.path">
                            <el-icon>
                                <component :is="item.meta.icon" :size="24"></component>
                            </el-icon>
                            <span>{
   
   { item.meta.title }}</span>
                        </router-link>
                    </template>
                    <menu-list :items="item.children" :mode="item.meta.mode"></menu-list>
                </el-sub-menu>
            </template>
            <template v-else>
                <el-menu-item :index="item.index" :key="item.path">
                    <router-link :to="item.path">
                        <el-icon>
                            <component :is="item.meta.icon" :size="24"></component>
                        </el-icon>
                        <span>{
   
   { item.meta.title }}</span>
                    </router-link>
                </el-menu-item>
            </template>
        </template>
    </el-menu>
</template>
<script>
export default {
    name: "menu-list",
    props: {
        customMenuClass: {
            type: String,
            required: false,
            default: "el-menu-class",
        },
        mode: {
            type: String,
            default: "horizontal",
        },
        items: {
            type: Array,
            required: true,
        },
        activeIndex: {
            type: String,
            required: false,
            default: "",
        }
    },
    data() {
        return {}
    },
    methods: {
        handleSelect(key, keyPath, menuItem) {
            this.$emit("select",{key, keyPath, menuItem})
        }
    }

}
</script>
<style lang="scss" scoped>
.el-menu-class {
    .el-menu-item:not(.is-disabled):hover {
        background-color: rgba(127, 255, 212, .3);
    }
}
</style>
<style lang="scss">
.el-sub-menu-popper-class {
    background-color: $base-background-color !important;
}
</style>

        使用示例如下,

//menuList变量对应的就是文章开头处给出的示例数据
 <MenuList :items="menuList" active-index="1" mode="horizontal"/>

        最终,我们就能完成这样的一个递归型菜单组件了,但是对于菜单的样式,可以根据实际需要进行定制。

猜你喜欢

转载自blog.csdn.net/weixin_43524214/article/details/131612496