您的位置:首页 > Web前端 > JavaScript

js实现后管无限级菜单递归一

2017-12-29 16:25 507 查看

递归后管菜单

递归就是函数自调用

之前做后管,刚开始后管菜单就三级,所有嵌套三层循环就可以.但是有些插件方需要四级或五级菜单.如果不用递归,一直嵌套循环也是可以的.只是写着写着觉得这样循环写代码太长了很难看.每次改动也很麻烦.再想能不能用递归做成自动化呢.

直接代码:

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
<link rel="stylesheet" href="https://cdn.bootcss.com/bootstrap/3.3.7/css/bootstrap.min.css">
<style>
* {margin: 0; padding: 0;}
ul {list-style: none;}
header {height: 60px;padding: 0 20px;line-height: 60px;background: #3c8dbc;}
.logo{float: left;}
.userinfo {float: right}
aside {position: fixed;left:0;top:0;width: 230px;height: 100%;margin-top: 60px;padding: 20px;background: #2d2d2d;color: #fff;}
.panel {margin-bottom: 0;}
aside>ul>li.panel {margin-bottom: 15px;}
</style>
</head>
<body>
<div class="wrap">
<header>
<div class="logo">logo</div>
<div class="userinfo">用户信息</div>
</header>
<aside id="aside"></aside>
<div class="content">
<iframe src="" frameborder="0"></iframe>
</div>
</div>
<script type="text/javascript" src="http://apps.bdimg.com/libs/jquery/2.1.4/jquery.min.js"></script>
<script type="text/javascript" src="http://apps.bdimg.com/libs/bootstrap/3.3.4/js/bootstrap.min.js"></script>
<script type="text/javascript">
//ajax后台请求得到的数据
var data = {"data": {"list": [
{"id": "no1", "name": "菜单管理", "url": "no1.do", "list": [
{"id": "no11", "name": "二级菜单-1", "url": "no11.do", "list": [
{"id": "no111", "name": "三级菜单-1", "url": "no111.do", "list": [
{"id": "no1111", "name": "四级菜单-1", "url": "no1111.do", "list": []},
{"id": "no1112", "name": "四级菜单-2", "url": "no1112.do", "list": []}
]},
{"id": "no112", "name": "三级菜单-2", "url": "no112.do", "list": [
{"id": "no1121", "name": "四级菜单-1", "url": "no1121.do", "list": []},
{"id": "no1122", "name": "四级菜单-2", "url": "no1122.do", "list": []}
]}
]},
{"id": "no12", "name": "二级菜单-2", "url": "no12.do", "list": [
{"id": "no121", "name": "三级菜单-1", "url": "no121.do", "list": [
{"id": "no1211", "name": "四级菜单-1", "url": "no1211.do", "list": []},
{"id": "no1212", "name": "四级菜单-2", "url": "no1212.do", "list": []}
]},
{"id": "no122", "name": "三级菜单-2", "url": "no122.do", "list": [
{"id": "no1221", "name": "四级菜单-1", "url": "no1221.do", "list": []},
{"id": "no1222", "name": "四级菜单-2", "url": "no1222.do", "list": []}
]}
]}
]},
{"id": "no2", "name": "一级菜单-2", "url": "no2.do", "list": [
{"id": "no21", "name": "二级菜单-1", "url": "no21.do", "list": [
{"id": "no211", "name": "三级菜单-1", "url": "no111.do", "list": [
{"id": "no2111", "name": "四级菜单-1", "url": "no1111.do", "list": []},
{"id": "no2112", "name": "四级菜单-2", "url": "no1112.do", "list": []}
]},
{"id": "no212", "name": "三级菜单-2", "url": "no212.do", "list": [
{"id": "no2121", "name": "四级菜单-1", "url": "no1121.do", "list": []},
{"id": "no2122", "name": "四级菜单-2", "url": "no1122.do", "list": []}
]}
]},
{"id": "no22", "name": "二级菜单-2", "url": "no22.do", "list": [
{"id": "no221", "name": "三级菜单-1", "url": "no221.do", "list": [
{"id": "no2211", "name": "四级菜单-1", "url": "no2211.do", "list": []},
{"id": "no2212", "name": "四级菜单-2", "url": "no2212.do", "list": []}
]},
{"id": "no222", "name": "三级菜单-2", "url": "no222.do", "list": [
{"id": "no2221", "name": "四级菜单-1", "url": "no2221.do", "list": []},
{"id": "no2222", "name": "四级菜单-2", "url": "no2222.do", "list": []}
]}
]}
]}
]}}
var res = data.data.list, html;
function asideTpl() {
var tpl = '<ul id="accordion" class="nav nav-sidbar">';
res.forEach(function(val) {
tpl += '<li class="panel"><a data-parent="#accordion" href="javascript:;" data-toggle="collapse" data-url="'+val.url+'" data-target="#parent-'+val.id+'" id="parent-a-'+val.id+'" class="parent jumpiframe">'
+ val.name + '</a><ul class="nav collapse" id="parent-'+val.id+'">'+createli(val.id, val.list, "")+'</ul></li>';
});
return tpl + '</ul';
}
function createli(pid, data, str) {
data && data.forEach(function(val) {
str += '<li class="panel"><a style="text-indent: 10px" href="javascript:;" data-toggle="collapse" data-parent="#parent-'+pid+'" data-url="'+val.url+'" data-target="#parent-'+val.id+'" id="parent-a-'+val.id+'" class="children jumpiframe">'
+ val.name + '</a><ul class="nav collapse" id="parent-'+val.id+'">'+createli(val.id, val.list, "")+'</ul></li>';
});
return str;
}
html = asideTpl();
document.querySelector('#aside').innerHTML = html;
$(".jumpiframe").on('click', function() {
var indent = $(this).css('text-indent'),
jumpClass = $(this).attr('class');
if (/children/.test(jumpClass)) {
$(this).next().children('li').children('a').css('text-indent', indent.match(/\d+/g)[0] - 0 + 10 + 'px');
}
})
</script>
</body>
</html>


代码分析

data是后台返回的对象数据(里面有很多嵌套)很难看,我这里写的还是简易版.真实的数据更多更复杂.如果大家看的晕,可以复制到浏览器查看

这个模板是用bootstrap-collapse来实现左侧菜单功能.样式是丑,但不是重点.重点是递归用法

如果不考虑”递归层次前缀显示”(找不到其它词了). 那么直接将data渲染为html.并不难.此处不做讲解

难点是”递归层次前缀显示”(这里用text-indent来表示).

举例:
{"id": "no1111", "name": "四级菜单-1", "url": "no1111.do", "list": []}
,这层对象在data对象里属于第三层嵌套,那么text-indent值就是30px.但是这个”3”怎么拿到了,这是难点.

我也测试很久,发现很难就放弃这种方法.改为通过事件来设置
$(this).next().children('li').children('a'))
的text-indent.这样点击时先获取点击父a标签的text-index.再设置所点击子菜单a标签的text-indent来间接实现”递归层次前缀显示”

后台返回一维数组递归(不是层级嵌套数据结构)

下次再介绍,
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息