前言
最近在学习react,想着之前vue用递归组件实现了配置化的菜单栏,那么是否可以用react也实现一次呢?毕竟react一个函数就是一个组件(虽然vue最终注册为组件时也是函数,但是vue-loader处理后的其实就是一个对象)。心动不如行动,下面我们就用react实现一次~
一、分析
其实相对于vue,react的递归更容易理解,实质上就是一个简单的递归函数。首先,选择主流的antd组件库作为我们的UI,避免重复繁琐的工作;然后,我们需要思考配置的数据结构,与路由router类似,是一个嵌套的数组对象结构,我们需要就是递归遍历这个数组。
二、实现
递归函数
import React from "react";
import { menuList } from './config'
type MenuItem = Required<MenuProps>['items'][number];// menuItem类型
// antd方法,用于返回menuItem需要的字段
function getItem( label: React.ReactNode, key: React.Key, icon?: React.ReactNode, children?: MenuItem[], type?: 'group'): MenuItem {
return {
key,
icon,
children,
label,
type,
} as MenuItem;
}
interface item {
key: string,
icon: string,
children: item[],
label: string,
type: string,
}
function getMenuList() {
let tempMenuList: ItemType[] = [];
let openKeys:string[] = [];
const getList = (list:any, newList: MenuItem[]) => {
for(let i=0; i<list.length; i++) {
const { value, label, icon } = list[i] || {};
const it = getItem(label, value || label);
newList.push(it)
routeMap[value] = label
if(tempBo) {
const tempItem = newList[i] as item
tempItem.children = [];
getList(list[i].children || [], tempItem.children);
}
}
}
getList(menuList, tempMenuList)
return {tempMenuList}
}
const MyMenu:React.FC<{bread:breadType}> = (props) => {
const { tempMenuList } = getMenuList()
return (
<Menu
style={{width:256, height:'100%'}}
mode="inline"
items={tempMenuList}
></Menu>
)
}
config配置菜单栏
export const menuList = [
{
value: '/home',
label: '首页',
},
{
value: '/form',
label: '表单系列',
children: [
{
value: '/form/loopForm',
label: '循环表单及校验'
}
]
},
{
value: '/components',
label: '封装组件',
children: [
{
value: '/components/inherit',
label: '二次封装组件功能透传'
},
{
value: '/components/table',
label: 'table组件',
}
]
},
{
value: '/skill',
label: '奇技淫巧',
}
]
效果
以上就实现了简单的配置化菜单栏了
三、总结
相较于vue的递归组件实现配置化菜单栏,react会更方便写,毕竟写递归函数相较而言会更容易上手。除了简单的配置菜单栏的label,其实也可以增加一些icon,路由等效果。
github地址:github.com/qiangguangl…
下期预告:
既然实现了配置化的菜单栏,如果想在项目中使用的话,肯定需要有一套路由管理系统了~ 下一期就引入react-router实现路由管理,顺便增加一些样式(增加icon配置~)