基于react实现无限分级菜单
在开发CMS(内容管理系统)系统时,一般都会用到一个侧边栏或者顶部的二级或者三级菜单,当点击或者鼠标悬浮时,菜单能够随之展开或收起。
本文纯粹为了练习一下react,因此我会在react环境下实现这么一个小组件:它假设了菜单数据来自于网络请求,并且仅实现无限分级菜单的核心功能(父子关系,展开与收起),至于样式则不是关注的重点。
分析&设计
既然要实现一个动态生成的无限分级菜单,最简单的切入思路就是分析一个静态的菜单:其DOM树是怎样构成的?
下面是一个典型的HTML结构:
<ul>
<li>
<h1>菜单1</h1>
<ul>
<li>
<h1>菜单1-1</h1>
<ul></ul>
</li>
</ul>
</li>
<li>
<h1>菜单2</h1>
<ul>
<li>
<h1>菜单2-1</h1>
<ul>
<li>
<h1>菜单2-1-1</h1>
<ul></ul>
</li>
</ul>
</li>
</ul>
</li>
</ul>
这是一个3级菜单,我们需要仔细观察它的构成规律:
- 首先<ul>代表了一个菜单列表,它里面包含了若干<li>代表其中1个菜单项。
- 每个<li>菜单项至少包含自己的标题,其次也应包含它下面的子菜单列表(也就是另一个<ul>)。
上述2个规则基本就是分级菜单的核心构思了,通过一个比较白话的描述可以这么理解:
要画一个菜单列表,那么就要去画它的每一个菜单项。
要画一个菜单项,那么就要画出标题,然后去画它的子菜单列表。
如果你反复的读上面的话,你可以感受到一种『递归的味道』。
没错,要根据菜单数据动态的画出一个无限分级的菜单是要用递归算法的。有意思的是,递归算法本身是深度优先的,而这恰好满足我们从上至下从外至内顺序追加HTML标签,从而最终构成完整的DOM树的编程思路。
数据结构&算法
程序设计=数据结构+算法。
因此,先用一个合理的数据结构来描述之前我们的构思,之后基于数据结构进行算法的实现,最终形成程序,这是我们正确的编程思路。
通常,菜单结构是服务端拼装的,它描述了菜单的父子和顺序关系,并且每个菜单拥有自己的唯一ID,这些都体现在我的render()方法中:
render() {
let data = [
{
menuId: 1,
name: '员工管理',
children: [
{
menuId: 3,
name: '添加员工',
children: []
},
{
menuId: 4,
name: '删除员工',
children: [
{
menuId: 6,
name: '按姓名删除',
children: []
},
{
menuId: 7,
name: '按工号删除',
children: []
}
]
}
],
},
{
menuId: 2,
name: '工资管理',
children: [
{
menuId: 5,
name: '修改工资',
children: []
}
],
},
];
return (
<div>
{this.generateMenu(data)}
</div>
);
}
最外层是一个菜单列表(Array),每个菜单项(Object)里有自己的标题,唯一ID,以及子菜单列表(Array)。
在render()方法里调用了我实现的递归算法generateMenu(data),根据上述数据结构和原理递归的生成了DOM树:
/**
* 递归生成菜单
* @param menuObj
* @returns {Array}
*/
generateMenu(menuObj) {
let vdom = []; if (menuObj instanceof Array) {
let list = [];
for (var item of menuObj) {
list.push(this.generateMenu(item));
}
vdom.push(
<ul key="single">
{list}
</ul>
);
} else {
vdom.push(
<li key={menuObj.menuId}>
<h1 onClick={this.onMenuClicked}>
{menuObj.name}
</h1>
{this.generateMenu(menuObj.children)}
</li>
);
}
return vdom;
}
- 第1个分支判断:如果当前对象是菜单列表(Array类型),那么应生成1个新的<ul>元素,并且递归画出每一个菜单项(Object类型)。
- 第2个分支判断:如果当前对象是菜单项(Object类型),那么应生成1个新的<li>元素,填充1个<h1>作为标题,其次递归画出它的子菜单列表。
最后,为了实现点击鼠标展开和收起菜单,我为每一个<h1>标签注册了onClick事件,当它们被点击时找到<h1>的兄弟<ul>元素(利用jquery搞定),修改其CSS display属性即可实现展现和隐藏其子菜单列表的效果了。
体验效果(react组件)
查看代码:https://github.com/owenliang/react/tree/master/component/MenuPage
查看demo:http://yuerblog.cc/wp-content/uploads/2016/11/output/#/menu-page
demo可以点击体验展开 or 收起
基于react实现无限分级菜单的更多相关文章
- 基于react可无限向内部添加节点的tree
这两天学习react,撸了一遍文档后开始自己动手写点东西. 正好从朋友那得到灵感,写一个小例子. 这个东西是这样的,就是点击的这个节点就往它里面添加一个child. 于是乎!我想到的就是用自调函数,递 ...
- 无限分级和tree结构数据增删改【提供Demo下载】
无限分级 很多时候我们不确定等级关系的层级,这个时候就需要用到无限分级了. 说到无限分级,又要扯到递归调用了.(据说频繁递归是很耗性能的),在此我们需要先设计好表机构,用来存储无限分级的数据.当然,以 ...
- C#使用二叉树算法设计一个无限分级的树表
效果图: 数据库: 操作树的示意图: 控制器代码: using Dw.Business; using Dw.Entity; using Dw.Utilities; using System; usin ...
- 前端基于react,后端基于.net core2.0的开发之路(1) 介绍
文章提纲目录 1.前端基于react,后端基于.net core2.0的开发之路(1) 介绍 2.前端基于react,后端基于.net core2.0的开发之路(2) 开发环境的配置,注意事项,后端数 ...
- 前端基于react,后端基于.net core2.0的开发之路(2) 开发环境的配置,注意事项,后端数据初始化
前端环境配置 项目介绍文章:前端基于react,后端基于.net core2.0的开发之路(1) 介绍 1.VSCode安装 下载地址:https://code.visualstudio.com/Do ...
- 放弃antd table,基于React手写一个虚拟滚动的表格
缘起 标题有点夸张,并不是完全放弃antd-table,毕竟在react的生态圈里,对国人来说,比较好用的PC端组件库,也就antd了.即便经历了2018年圣诞彩蛋事件,antd的使用者也不仅不减,反 ...
- 基于React实现的【绿色版电子书阅读器】,支持离线下载
代码地址如下:http://www.demodashi.com/demo/12052.html MyReader 绿色版电子书阅读器 在线地址:http://myreader.linxins.com ...
- JS组件系列——基于Bootstrap Ace模板的菜单和Tab页效果分享(你值得拥有)
前言:最近园子里多了许多谈语言.谈环境.谈逼格(格局)的文章,看看笑笑过后,殊不知其实都是然并卵.提升自己的技术才是王道.之前博主分享过多篇bootstrap组件的文章,引起了很多园友的关注和支持,看 ...
- 基于 React.js + Redux + Bootstrap 的 Ruby China 示例 (转)
一直学 REACT + METEOR 但路由部分有点问题,参考一下:基于 React.js + Redux + Bootstrap 的 Ruby China 示例 http://react-china ...
随机推荐
- EasyMesh - A Two-Dimensional Quality Mesh Generator
EasyMesh - A Two-Dimensional Quality Mesh Generator eryar@163.com Abstract. EasyMesh is developed by ...
- HTTPS简介
一.简单总结 1.HTTPS概念总结 HTTPS 就是对HTTP进行了TLS或SSL加密. 应用层的HTTP协议通过传输层的TCP协议来传输,HTTPS 在 HTTP和 TCP中间加了一层TLS/SS ...
- LeetCode[5] 最长的回文子串
题目描述 Given a string S, find the longest palindromic substring in S. You may assume that the maximum ...
- C#中如何在Excel工作表创建混合型图表
在进行图表分析的时候,我们可能需要在一张图表呈现两个或多个样式的图表,以便更加清晰.直观地查看不同的数据大小和变化趋势.在这篇文章中,我将分享C#中如何在一张图表中创建不同的图表类型,其中包括如何在同 ...
- P2V之后的磁盘扩容新思路
背景: 原先的物理机环境多是若干块物理磁盘经过RAID卡进行了RAID5之后的虚拟磁盘组,这样我们在操作系统内看到的也就是一块完整的磁盘.我们会在上面进行分区,然后格式化后以便使用. Figure 1 ...
- 玩转spring boot——AOP与表单验证
AOP在大多数的情况下的应用场景是:日志和验证.至于AOP的理论知识我就不做赘述.而AOP的通知类型有好几种,今天的例子我只选一个有代表意义的“环绕通知”来演示. 一.AOP入门 修改“pom.xml ...
- GSD_WeiXin(高仿微信)应用源码
高仿微信计划:已经实现功能 1.微信首页(cell侧滑编辑.下拉眼睛动画.下拉拍短视频.点击进入聊天详情界面) 2.通讯录(联系人字母排序.搜索界面) 3.发现(朋友圈) 4.我(界面) 待实现功能( ...
- A*算法应用[转]
转自:http://www.cnblogs.com/zhoug2020/p/3468167.html 这是一篇十分精彩/易懂的博客,感谢原博主!本文通过自己的理解在原博文基础上突出一些重点字眼,句子. ...
- ramdisk plus v11.5安装内存虚拟硬盘
ramdisk plus v11.5.桌面版操作及应用图解说明 一.ramdisk plus程序安装方法: 1.先安装英文原版软件(RamDisk-desktop.exe桌面版),安装路径不要更改,安 ...
- SQL Server的AlwaysOn错误19456和41158
SQL Server的AlwaysOn错误19456和41158 最近在公司搞异地数据库容灾,使用AlwaysOn的异地节点进行数据同步,在搭建的过程中遇到了一些问题 软件版本 SQL Server2 ...