持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第13天,点击查看活动详情
在我工作中遇到的项目里,菜单通常是一个json格式的文件。
在这个json中有菜单的id、菜单名称、图标class、排序号、权限清单id、嵌套子菜单等信息。
其实细看起来,包含的信息还是很多的。
就因为这个信息过多,很多时候如何把他渲染到页面上,会很棘手。
不要怕,直接不看干扰信息,找到关键信息,一个遍历,不行就再来一个遍历。
无论用多low的方法,哪怕if-else嵌套也行啊,第一步的任务就是:先用代码实现它。
然后再逐步优化它
菜单的json格式
要说这个json格式,通常有两种:一维、多维(嵌套)
//一维
[
{},
{},
{},
{}
....
]
//多维
[{},
[
{},
[
{},
{}
]
],
[
{},
{}
]
]
这两种遍历的方式不一样,但是也差不多
因为既然是菜单,肯定不只有一级菜单,一般是多级(遍历程序默认支持无穷级那种)
一维格式同样可以达到多级菜单的目的,加个字段即可...
遍历一维菜单的json文件
废话不多说,直接上菜单json
var data = [
{
"id": 1,
"name": "办公管理",
"pid": 0
},
{
"id": 2,
"name": "请假申请",
"pid": 1
},
{
"id": 3,
"name": "出差申请",
"pid": 1
},
{
"id": 4,
"name": "请假记录",
"pid": 2
},
{
"id": 5,
"name": "系统设置",
"pid": 0
},
{
"id": 6,
"name": "权限管理",
"pid": 5
},
{
"id": 7,
"name": "用户角色",
"pid": 6
},
{
"id": 8,
"name": "菜单设置",
"pid": 6
}
]
如上 pid 表示 菜单的父级id,从而实现层级效果!如果pid为空或0,则表示一级根菜单。
想想看如何遍历比较好?
思路分析:
循环遍历这个json文件
然后根据当前id,找到所有pid和这个id相同的项,组成一个临时数组 ---> 这个就是当前的子菜单集合
如果临时数组中id,还有pid和它相同,那就是子菜单的子菜单....这不就是递归了
关键:对,把如何找子菜单集合的方法单独拿出来,因为它和递归业务没有直接关系,这种找集合的逻辑不要放到循环遍历的逻辑里面
我的代码如下
<script>
let menu = "";
let app = {
getTree: function(id, arr) {
let childArr = this.getParentArray(id, arr);
if (childArr.length > 0) {
menu += "<ul>";
for (let i in childArr) {
menu += "<li>" + childArr[i].name;
this.getTree(childArr[i].id, arr); //递归调用
menu += "</li>";
}
menu += "</ul>";
}
},
//子菜单集合获取方法
getParentArray: function(id, arr) {
let newArr = [];
for (let i in arr) {
if (arr[i].pid === id) {
newArr.push(arr[i]);
}
}
return newArr;
}
};
//调用并输出
app.getTree(0, data);
$(document.body).append(menu);
渲染效果
看完代码是不是很简单?
但真要空手去实现,一次性并不会写的那么完美,而是多次修改迭代,抽离之后得出来的代码,虽说不算什么高深,但还是需要一定技巧的
另外还需要说一点的是:找集合的方法,其实就是在杂乱无序的对象中找到属于自己的下级,至于下级的下级,或上级,那就不是本次遍历考虑的了,而是递归方法里考虑了,它就像一个螺旋结构一样。
再重复一遍,而找子集的方法抽出来很重要,不然方法会显得臃肿(在这里的demo不明显,但是实际项目中会复杂的多)
另外,如何遍历多维菜单json文件,下文再说吧,本文先到这里。
留个坑,大家可以先想想代码怎么写
文末总结
有时候遇到一个棘手的问题时,首先不能怕
找到切入点,迎难而上,很快就能发现,问题并不难解决
先写出雏形,慢慢再优化,最后找到完美代码
万变不离其宗,难的是开头,要不怎么说:万事开头难呢