今天在处理递归无限层级菜单时,遇到一个稍微烧脑的问题,如何显示当前节点所在的层级数。
废话不多说,我们先看个直观的无限层级:

<?php
// 这里的arr是直接从数据库取出的,仅作为测试数据
$arr = array(array('id' => 1, 'name' => '一级菜单a', 'pid' => 0),// pid 父级idarray('id' => 2, 'name' => '一级菜单b', 'pid' => 0),array('id' => 3, 'name' => '二级菜单a', 'pid' => 1),array('id' => 4, 'name' => '二级菜单b', 'pid' => 1),array('id' => 5, 'name' => '二级菜单c', 'pid' => 2),array('id' => 6, 'name' => '二级菜单d', 'pid' => 2),array('id' => 7, 'name' => '三级菜单a', 'pid' => 3),array('id' => 8, 'name' => '三级菜单b', 'pid' => 3),array('id' => 9, 'name' => '四级菜单a', 'pid' => 8),
);/** 获取所有子节点* @param $data 所有节点数组* @param $id   $pid 父级节点id* @param $level  层级* @return array*/
function getTree($data, $pid, $level = 0)
{$list = array();foreach ($data as $k => $v) {if ($v['pid'] == $pid) {$v['level'] = $level;$v['name'] = $v['name'].'('.($level+1).'级)'; // 这里可以加个层级次数$v['children'] = getTree($data, $v['id'], $level + 1);if ($v['children'] == null){unset($v['children']);}$list[] = $v;}}return $list;
}$menu = getTree($arr, 0, 0);$json = json_encode($menu);
?>
<!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><script src="https://cdn.jsdelivr.net/npm/vue"></script><style>*{box-sizing: border-box;margin: 0;padding: 0;}*:before,*:after{box-sizing: border-box;}ul,li {list-style: none;}.l_tree_container {width: 100%;height: 100%;box-shadow: 0 0 3px #ccc;margin: 13px;position: relative;}.l_tree {width: calc(100% - 44px);height: 100%;padding-left: 42px;}.l_tree_branch {width: 100%;height: 100%;display: block;padding: 13px;position: relative;}.l_tree_branch .l_tree_children_btn {width: 19px;height: 19px;background-color: #23b1f0;font-size: 14px;text-align: center;color: #ffffff;outline: none;border: 0;cursor: pointer;}ul.l_tree:before {content: '';border-left: 1px dashed #999999;height: calc(100%);position: absolute;left: 10px;top: 0px;}.l_tree .l_tree_branch:last-child::before {content: '';width: 3px;height: calc(100% - 24px);display: block;background-color: #ffffff;position: absolute;bottom: 0;left: -34px;}.l_tree,.l_tree_branch {position: relative;}.l_tree_branch::after {content: '';width: 40px;height: 0;border-bottom: 1px dashed #000;position: absolute;right: calc(100% - 9px);top: 22px;}.l_tree_container>.l_tree::before,.l_tree_container>.l_tree>.l_tree_branch::after {display: none;}</style>
</head><body><div id="demo"><div class="l_tree_container"><ew-tree :model="testdata"></ew-tree></div>
</div><script>// 树组件Vue.component('ew-tree', {template: `<ul class="l_tree"><li class="l_tree_branch" v-for="item in model" :key="item.id"><div class="l_tree_click"><button type="button" class="l_tree_children_btn" v-if="item.children"  @click="toggle(item)">{{ !item.show ? '-' : '+' }}</button><span class="l_folder">{{ item.name }}</span></div><ew-tree v-show="!item.show" v-if="item.children" :model="item.children"></ew-tree></li></ul>`,props: {model: {}},methods: {toggle: function (item) {var idx = this.model.indexOf(item)Vue.set(this.model[idx], 'show', !item.show)}}});new Vue({el: "#demo",data() {return {testdata: <?php echo $json?>}}})
</script></body>
</html>

我们看到所有节点层级数没问题,那么我如何查看节点中pid=3的所有节点层级关系呢

$menu = getTree($arr, 3, 0);

显然不对,况且菜单展示并不友好,pid=3的父节点至少要显示在顶层吧。层级数暂且不管,我们先解决如何显示顶层pid=3的树形结构:
pid=3对应的节点是:二级菜单a。这个可以直接根据数据id查询出来,此处仅做演示哈。调整下代码:

$menu = getTree($arr, 3, 0);
$menu = array(['name' => '二级菜单a','children'=> $menu]);
$json = json_encode($menu);

OK,完美,同样要显示所有pid=1的节点层级关系,一样,pid=1对应的节点是 一级菜单a

$menu = getTree($arr, 1, 0);
$menu = array(['name' => '一级菜单a','children'=> $menu]);
$json = json_encode($menu);

好,回到 刚才的话题,如何正确的显示每个节点所在的层级数呢? 这里我也思考了很久,也没找到快捷的方法。
最终我还是递归的查询本节点所有的父节点id集合:完整代码如下:

<?php
// 这里的arr是直接从数据库取出的,仅作为测试数据
$arr = array(array('id' => 1, 'name' => '一级菜单a', 'pid' => 0),// pid 父级idarray('id' => 2, 'name' => '一级菜单b', 'pid' => 0),array('id' => 3, 'name' => '二级菜单a', 'pid' => 1),array('id' => 4, 'name' => '二级菜单b', 'pid' => 1),array('id' => 5, 'name' => '二级菜单c', 'pid' => 2),array('id' => 6, 'name' => '二级菜单d', 'pid' => 2),array('id' => 7, 'name' => '三级菜单a', 'pid' => 3),array('id' => 8, 'name' => '三级菜单b', 'pid' => 3),array('id' => 9, 'name' => '四级菜单a', 'pid' => 8),
);/** 获取所有子节点* @param $data 所有节点数组* @param $id $pid 父级节点id* @param $level  层级* @return array*/
function getTree($data, $pid, $level = 0)
{$list = array();foreach ($data as $k => $v) {if ($v['pid'] == $pid) {$v['level'] = $level;$v['name'] = $v['name'] . '(' . ($level + 1) . '级)'; // 这里可以加个层级次数$v['children'] = getTree($data, $v['id'], $level + 1);if ($v['children'] == null) {unset($v['children']);}$list[] = $v;}}return $list;
}/** 根据子节点获取父节点id* @param $data 所有节点数组* @param $id   id  主键id* @return array*/
function getParentid($data, $id)
{$arr = array();foreach ($data as $v) {if ($v['id'] == $id) {$arr[] = $v;//$arr[$v['id']]=$v['name'];$arr = array_merge(getParentid($data, $v['pid']), $arr);}}return $arr;}$id = 8 ; // 对应的节点是: 三级菜单b 对应的pid 是 3
$pid = 3; // 对应的节点是  二级菜单a$toparr = getParentid($arr, $id); // 节点为8的所有父节点 id: 1 3  8 这里包含了自身,注意剔除$level = count($toparr); // 节点所在的层级数
$menu = getTree($arr, $pid, $level-1);
if($pid)$menu = array(['name' => '二级菜单a' . '(' . ($level-1) . '级)', 'children' => $menu]);$json = json_encode($menu);
?>
<!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><script src="https://cdn.jsdelivr.net/npm/vue"></script><style>* {box-sizing: border-box;margin: 0;padding: 0;}*:before, *:after {box-sizing: border-box;}ul,li {list-style: none;}.l_tree_container {width: 100%;height: 100%;box-shadow: 0 0 3px #ccc;margin: 13px;position: relative;}.l_tree {width: calc(100% - 44px);height: 100%;padding-left: 42px;}.l_tree_branch {width: 100%;height: 100%;display: block;padding: 13px;position: relative;}.l_tree_branch .l_tree_children_btn {width: 19px;height: 19px;background-color: #23b1f0;font-size: 14px;text-align: center;color: #ffffff;outline: none;border: 0;cursor: pointer;}ul.l_tree:before {content: '';border-left: 1px dashed #999999;height: calc(100%);position: absolute;left: 10px;top: 0px;}.l_tree .l_tree_branch:last-child::before {content: '';width: 3px;height: calc(100% - 24px);display: block;background-color: #ffffff;position: absolute;bottom: 0;left: -34px;}.l_tree,.l_tree_branch {position: relative;}.l_tree_branch::after {content: '';width: 40px;height: 0;border-bottom: 1px dashed #000;position: absolute;right: calc(100% - 9px);top: 22px;}.l_tree_container > .l_tree::before,.l_tree_container > .l_tree > .l_tree_branch::after {display: none;}</style>
</head><body><div id="demo"><div class="l_tree_container"><ew-tree :model="testdata"></ew-tree></div>
</div><script>// 树组件Vue.component('ew-tree', {template: `<ul class="l_tree"><li class="l_tree_branch" v-for="item in model" :key="item.id"><div class="l_tree_click"><button type="button" class="l_tree_children_btn" v-if="item.children"  @click="toggle(item)">{{ !item.show ? '-' : '+' }}</button><span class="l_folder">{{ item.name }}</span></div><ew-tree v-show="!item.show" v-if="item.children" :model="item.children"></ew-tree></li></ul>`,props: {model: {}},methods: {toggle: function (item) {var idx = this.model.indexOf(item)Vue.set(this.model[idx], 'show', !item.show)}}});new Vue({el: "#demo",data() {return {testdata: <?php echo $json?>}}})
</script></body>
</html>

同样要显示所有节点:直接把pid赋值0,比如:

$id = 2 ; // 对应的节点是: 一级菜单b 对应的pid 是 0
$pid = 0; // 对应的节点是 0 为 一级节点  显示所有节点,上面的$id用不到$toparr = getParentid($arr, $id); //$level = count($toparr); // 节点所在的层级数
$menu = getTree($arr, $pid, $level-1);
if($pid)$menu = array(['name' => '二级菜单a' . '(' . ($level-1) . '级)', 'children' => $menu]);$json = json_encode($menu);

看起来没毛病,博友们如果有好的办法获取任意一个节点所处的层级数,欢迎拍砖留言哈。

转载于:https://www.cnblogs.com/applelife/p/11016616.html

Php无限层级并显示层级数相关推荐

  1. 132:vue+openlayers: 设置显示图层的层级数zIndex (示例代码)

    第132个 点击查看专栏目录 本示例的目的是介绍演示如何在vue+openlayers中设置显示层级数zIndex.每一个图层都像一张纸似的,叠加在一起,上面的层级数zIndex值高,下面的层级数小. ...

  2. 小程序无限层级路由方案

    作者:大转转FE-吴鹏和 小程序原生页面存在层级限制,超过一定层数就会无法打开新页面.一开始这个限制为不超过5层,目前是不超过10层. 这个限制对于体量较大的小程序来说,挺难受的.特别是只能打开5层那 ...

  3. easyUI-树形菜单(ComboTree) 无限层级树实现方式(1.0版本)

    对于easyUI实现一个树,是一件很简单的事情,实现形式很多.这里作者将实现,通过数据库获取数据,再将数据通过递归形式装成无限层级json数据,到达无限成级的树结构.需要用到的json插件建附件,希望 ...

  4. WebAPI增加Area以支持无限层级同名Controller

    原文:WebAPI增加Area以支持无限层级同名Controller 微软的WebAPI默认实现逻辑 默认实现中不支持同名Controller,否则在访问时会报HttpError,在网上找到了各种路由 ...

  5. Android上的MVP:如何组织显示层的内容

    MVP(Model View Presenter)模式是著名的MVC(Model View Controller)模式的一个演化版本,目前它在Android应用开发中越来越重要了,大家也都在讨论关于M ...

  6. php 递归递实现无限层级

    项目场景 php递归递实现无限层级: 项目场景:示例:网站栏目,商品分类 @Override//递归查找子级栏目 实现无限层级public function getTree($data, $pId){ ...

  7. Java中的无限层级递归树前后端操作解决方案

    引言: 抖音真是一个神奇的软件,前两天脑海中浮现了一首歌,知道歌曲的调调,今天打算写博客之前刷了一下抖音,抖音的推荐算法居然给我推送了这首歌,这首歌叫做<一开始说陪你到老的人现在他还好吗> ...

  8. C# 导航栏无限层级树

    #region 获取导航栏方法-无限层级         /// <summary>         /// 获取导航栏方法-无限层级         /// </summary&g ...

  9. boot spring 简拼_超牛逼的下拉字典框架,支持拼音简拼搜索,代码项、代码值搜索,无限层级级联,多选、过滤自定义数据表等等...

    Dic扩展模块 Dic数据字典模块是v-ci的核心之一,为解决大数据量下拉字典效率及操作问题,特推出通用的数据字典模块,所有字典数据可在数据库维护,在大数据量时采用分页下拉的展示方式,同时支持拼音简拼 ...

最新文章

  1. 程序员MM的自白:磨人小妖精之安卓碎片化
  2. 【铜】第174-9篇 一对一视频录制(九)一对多学生端删除白板及nginx下配CI
  3. 告别苦逼的程序员生涯,我的CTO之路!
  4. 上传文件到 Web 服务器
  5. Binder源码分析之驱动层(原)
  6. c 对一个mysql数据库进行操作_用C语言操作MySQL数据库
  7. 如何修改作者名称_PS2019中如何扩展文本选区 ps扩展文本选区的图文教程_photoshop教程...
  8. QT的QFormLayout类的使用
  9. 16-就业课(2.1)-应用容器-Docker
  10. 1.Intro to Deep Learning and Computer Vision
  11. 从零开始学习PYTHON3讲义(二)把Python当做计算器
  12. BZOJ1026: [SCOI2009]windy数(数位dp)
  13. 【招】阿里云技术战略高级专家
  14. VScode:禁止VScode自动升级
  15. vue项目无法启动,谷歌浏览器报:您与此网站之间建立的连接不安全,实际是cdn服务器过期
  16. Altium Designer Summer 9 Build 9.4.0.20159下载地址 + 破解补丁
  17. 基于JAVA中小学教师培训管理系统计算机毕业设计源码+系统+数据库+lw文档+部署
  18. Windos 系统安装 Themebeta Chrome主题
  19. 学习PLC编程的9个建议
  20. 物联1902-631907090123-谢林

热门文章

  1. Emmet快速编写HTML代码
  2. 大数据量表的优化查询
  3. pku 1321 棋盘问题 DFS
  4. 开发smartphone应用,无法生成cab文件?
  5. 01Hypertext Preprocessor
  6. 如何将卷积神经网络中的全连接层变成卷积层
  7. gitlab服务器搭建教程
  8. 《python基础教程》笔记之 列表
  9. Oracle 安装报错 [INS-06101] IP address of localhost could not be determined 解决方法[转]
  10. 在Android中调用KSOAP2库访问webservice服务出现的服务端传入参数为null的问题解决