赞
踩
本文分别使用 SFC(模板方式)和 tsx 方式对 Element Plus el-menu 组件进行二次封装,实现配置化的菜单,有了配置化的菜单,后续便可以根据路由动态渲染菜单。
使用 element-plus el-menu 组件实现菜单,主要包括三个组件:
el-menu:整个菜单;
el-sub-menu:含有子菜单的菜单项;
el-sub-menu:没有子菜单的菜单项(最末级);
结合菜单的属性和展示效果,可以得到每个菜单项包括:菜单名称、菜单图标、菜单唯一标识、子菜单列表四个属性。于是可得到菜单项结构定义如下:
/** * 菜单项 */ export interface MenuItem { /** * 菜单名称 */ title: string; /** * 菜单编码(对应 el-menu-item / el-sub-menu 组件的唯一标识 index 字段) */ code: string; /** * 菜单的图标 */ icon?: string; /** * 子菜单 */ children?: MenuItem[] }
传入 MenuItem 数组,使用该数组渲染出菜单。但有时候数据字段不一定为上面结构定义的属性名,如 菜单名称 字段,上面定义的属性为 title,但实际开发过程中后端返回的是 name,此时字段名不匹配。一种处理方式是前端开发获取到后台返回的数据后,遍历构造上述结构,由于是树形结构,遍历起来麻烦。另一种方式是由用户指定字段的属性名,分别指定菜单名称、菜单编码等分别对应用户传递数据的什么字段。所以需要再定义一个结构,由用户来配置字段名称。
首先定义菜单项字段配置的结构:
/**
* 菜单项字段配置结构
*/
export interface MenuOptions {
title?: string;
code?: string;
icon?: string;
children?: string;
}
再定义菜单项结构默认字段名:
/**
* 菜单项默认字段名称
*/
export const defaultMenuOptions: MenuOptions = {
title: 'title',
code: 'code',
icon: 'icon',
children: 'children'
}
通常使用 tsx 封装组件的结构如下:
import { defineComponent } from 'vue' export default defineComponent({ name: 'yyg-menu', // 属性定义 props: { }, setup (props, context) { console.log(props, context) return () => ( <div>yyg-menu</div> ) } })
首先定义两个属性:菜单的数据、菜单数据的字段名。
// 属性定义 props: { data: { type: Array as PropType<MenuItem[]>, required: true }, menuOptions: { type: Object as PropType<MenuOptions>, required: false, default: () => ({ }) } },
除了上面定义的两个属性,el-menu 中的属性我们也希望能够暴露出去使用:
但 el-menu 的属性太多,一个个定义不太现实,在 tsx 中可以使用 context.attrs 来获取。
context.attrs 会返回当前组件定义的属性之外、用户传入的其他属性,也就是返回没有在 props 中定义的属性。
在 setup 中 递归 实现菜单的无限级渲染。封装函数 renderMenu,该函数接收一个数组,遍历数组:
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。