js 递归json树实现根据子id查父id的方法分析


Posted in Javascript onNovember 08, 2019

本文实例讲述了js 递归json树实现根据子id查父id的方法。分享给大家供大家参考,具体如下:

最近做了一个类似用js实现思维导图的功能,作为思维导图,一定会有树状结构的数据产生,在操作里面的节点时会经常需要查找节点 的父节点及父节点。

对于未知层级的树状数据,用for循环是无法实现的,因为不知道要循环几层,那么最合适的方法就是用js递归

界面结构:

js 递归json树实现根据子id查父id的方法分析

json数据:

"orgTreeData":{
  "nodeId":"19A5B",
  "nodeName":"预分析用户:1313.85万人",
  "nodeType":"root",
  "expand":true,
  "dataCnt":13138494,
  "children":[
    {
      "nodeId":"19A5B_19A5C",
      "nodeName":"客户状态",
      "nodeType":"tag",
      "children":[
        {
          "nodeId":"19A5B_19A5C_19A5E",
          "nodeName":"包含(实名制停机,IPBUS帐户封锁停机)",
          "dataCnt":"0人",
          "nodeType":"domain",
          "counted":2,
          "children":[
            {
              "nodeId":"19A5B_19A5C_19A5E_19A67",
              "nodeName":"积分",
              "nodeType":"tag",
              "children":[
              ],
              "expand":true,
              "counted":0,
              "condType":"1",
              "dataType":1,
              "propType":"1",
              "propSql":"",
              "labelId":"BLD00013",
              "linked":false,
              "linkedId":""
            },
            {
              "nodeId":"19A5B_19A5C_19A5E_19A68",
              "nodeName":"是否通信客户",
              "nodeType":"tag",
              "children":[
              ],
              "expand":true,
              "counted":0,
              "condType":"3",
              "dataType":1,
              "propType":"4",
              "propSql":"",
              "labelId":"BLD00010",
              "linked":false,
              "linkedId":""
            }
          ],
          "expand":true,
          "expressType":"7",
          "expressValue1":[
            "17",
            "14"
          ],
          "expressValue2":"",
          "expressValue3":"17##14",
          "expressValue4":"实名制停机##IPBUS帐户封锁停机",
          "expressValue5":"实名制停机,IPBUS帐户封锁停机",
          "linked":false,
          "linkedId":""
        },
        {
          "nodeId":"19A5B_19A5C_19A60",
          "nodeName":"包含(营业销户)",
          "dataCnt":"0人",
          "nodeType":"domain",
          "counted":2,
          "children":[
            {
              "nodeId":"19A5B_19A5C_19A60_19A69",
              "nodeName":"入网归属地域",
              "nodeType":"tag",
              "children":[
                {
                  "nodeId":"19A5B_19A5C_19A60_19A69_19A6A",
                  "nodeName":"包含(鄂尔多斯,阿盟)",
                  "dataCnt":"",
                  "nodeType":"domain",
                  "counted":0,
                  "children":[
                  ],
                  "expand":true,
                  "expressType":"7",
                  "expressValue1":[
                    "477",
                    "482"
                  ],
                  "expressValue2":"",
                  "expressValue3":"477##482",
                  "expressValue4":"鄂尔多斯##阿盟",
                  "expressValue5":"鄂尔多斯,阿盟",
                  "linked":false,
                  "linkedId":""
                }
              ],
              "expand":true,
              "counted":0,
              "condType":"2",
              "dataType":1,
              "propType":"3",
              "propSql":"1005",
              "labelId":"BLD00017",
              "linked":false,
              "linkedId":""
            }
          ],
          "expand":true,
          "expressType":"7",
          "expressValue1":[
            "40"
          ],
          "expressValue2":"",
          "expressValue3":"40",
          "expressValue4":"营业销户",
          "expressValue5":"营业销户",
          "linked":false,
          "linkedId":""
        }
      ],
      "expand":true,
      "counted":0,
      "condType":"2",
      "dataType":1,
      "propType":"3",
      "propSql":"1002",
      "labelId":"BLD00004",
      "linked":false,
      "linkedId":""
    },
    {
      "nodeId":"19A5B_19A61",
      "nodeName":"全球通级别 && 全球通级别",
      "nodeType":"tag",
      "children":[
      ],
      "expand":true,
      "counted":0,
      "condType":"2",
      "dataType":1,
      "propType":"3",
      "propSql":"1004",
      "labelId":"BLD00008",
      "linked":true,
      "linkedId":"19A5B_19A64"
    },
    {
      "nodeId":"19A5B_19A62",
      "nodeName":"同证件号码数量",
      "nodeType":"tag",
      "children":[
      ],
      "expand":true,
      "counted":0,
      "condType":"1",
      "dataType":1,
      "propType":"1",
      "propSql":"",
      "labelId":"BLD00009",
      "linked":false,
      "linkedId":""
    }
  ]
}

我这个对象结构是按nodeId匹配的,每个下级为children数组。

如果我想点击任何一个节点根据节点nodeId得到它的父节点nodeId,就得把整个json树递归遍历一遍,知道找到这个节点,从而得到它的父节点

关于递归,一定要掌握好结束条件,懂得何时return,不然会出现返回不出值或者循环提前结束的情况。

js代码:

//传入参数:需要遍历的json,需要匹配的id
findPnodeId(data,nodeId){
    //设置结果
    let result;
    if (!data) {
        return;//如果data传空,直接返回
    }
    for (var i = 0; i < data.children.length; i++) {
        let item = data.children[i];
        if (item.nodeId == nodeId) {
            result=data.nodeId;
        //找到id相等的则返回父id
            return result;
        } else if (item.children && item.children.length > 0) {
        //如果有子集,则把子集作为参数重新执行本方法
            result= findPnodeId(item, nodeId);
        //关键,千万不要直接return本方法,不然即使没有返回值也会将返回return,导致最外层循环中断,直接返回undefined,要有返回值才return才对
            if(result){
                return result;
            }
        }
    }
    //如果执行循环中都没有return,则在此return
    return result;
}

js 递归json树实现根据子id查父id的方法分析

总之,递归相当于上图中的轨迹查找。

条件执行到 需要 重新执行 findPnodeId 方法的地方开始一头扎进去,如果第下一次执行找到了符合条件的值,则return出来,返回上一层,下一层的 findPnodeId 方法结束,返回值,上一层的findPnodeId方法也就直接return结束了。

js 递归json树实现根据子id查父id的方法分析

如果下一层方法 进入循环第一次依然没有找到 符合的值 ,如果还有子集,则会继续向更下一层进发;就像上图中的红线,直到没有子集才结束,所以千万不让直接 在递归 findPnodeId 方法前直接return,也就是这样:

else if (item.children && item.children.length > 0) {
    return findPnodeId(item, nodeId);
}

这样会使 json在第一条树轨迹结束时(上图中的红色轨迹)如果找不到值 强制 retrun undefined,因为没一个方法都向上return,for循环中,一旦return,会直接打断循环,使方法结束,结果是最底层 的undefined 直接return到顶层,顶层直接将undefined return出来,根本没有走第234条线,所以一定要先判断一下是否返回值再return,像这样:

} else if (item.children && item.children.length > 0) {
    result= this.findPnodeId(item, nodeId);
    if(result){
        return result;
    }
}

那么如果方法前不写return会怎样?

是方法无法return,依然无法递归

Javascript 相关文章推荐
静态的动态续篇之来点XML
Dec 23 Javascript
Javascript图像处理—平滑处理实现原理
Dec 28 Javascript
js网页中的(运行代码)功能实现思路
Feb 04 Javascript
深入理解JavaScript系列(48):对象创建模式(下篇)
Mar 04 Javascript
深入理解JavaScript中的浮点数
May 18 Javascript
jQuery ajax调用后台aspx后台文件的两种常见方法(不是ashx)
Jun 28 Javascript
JS 数字转换为大写金额的简单实例
Aug 04 Javascript
实例解析jQuery中如何取消后续执行内容
Dec 01 Javascript
JavaScript正则表达式简单实用实例
Jun 23 Javascript
浅谈在koa2中实现页面渲染的全局数据
Oct 09 Javascript
Vue2.0中集成UEditor富文本编辑器的方法
Mar 03 Javascript
js实现ATM机存取款功能
Oct 27 Javascript
BootstrapValidator验证用户名已存在(ajax)
Nov 08 #Javascript
微信小程序在text文本实现多种字体样式
Nov 08 #Javascript
浅谈vuex的基本用法和mapaction传值问题
Nov 08 #Javascript
微信小程序select下拉框实现源码
Nov 08 #Javascript
使用kbone解决Vue项目同时支持小程序问题
Nov 08 #Javascript
在VUE中实现文件下载并判断状态的方法
Nov 08 #Javascript
vue中在vuex的actions中请求数据实例
Nov 08 #Javascript
You might like
PHP初学者常见问题集合 修正版(21问答)
2010/03/23 PHP
php获得用户ip地址的比较不错的方法
2014/02/08 PHP
php使用Jpgraph绘制柱形图的方法
2015/06/10 PHP
PHP并发查询MySQL的实例代码
2017/08/09 PHP
json跟xml的对比分析
2008/06/10 Javascript
基于jQuery的固定表格头部的代码(IE6,7,8测试通过)
2010/05/18 Javascript
JS 退出系统并跳转到登录界面的实现代码
2013/06/29 Javascript
MyEclipse取消验证Js的两种方法
2013/11/14 Javascript
如何判断元素是否为HTMLElement元素
2013/12/06 Javascript
JS 排序输出实现table行号自增前端动态生成的tr
2014/08/13 Javascript
深入理解JavaScript系列(50):Function模式(下篇)
2015/03/04 Javascript
JavaScript 字符串数字左补位,右补位,取固定长度,截位扩展函数代码
2017/03/25 Javascript
vue跨域解决方法
2017/10/15 Javascript
浅析Vue 生命周期
2018/06/21 Javascript
详解javascript中的babel到底是什么
2018/06/21 Javascript
JavaScript基于对象方法实现数组去重及排序操作示例
2018/07/10 Javascript
Vue快速实现通用表单验证的方法
2020/02/24 Javascript
vue+axios全局添加请求头和参数操作
2020/07/24 Javascript
使用Python对SQLite数据库操作
2017/04/06 Python
在python中pandas的series合并方法
2018/11/12 Python
Python装饰器限制函数运行时间超时则退出执行
2019/04/09 Python
python中的句柄操作的方法示例
2019/06/20 Python
python logging.info在终端没输出的解决
2020/05/12 Python
python如何导出微信公众号文章方法详解
2020/08/31 Python
python批量修改文件名的示例
2020/09/27 Python
css3打造一款漂亮的卡哇伊按钮
2013/03/20 HTML / CSS
瑞士图书网站:Weltbild.ch
2019/09/17 全球购物
生产厂厂长岗位职责
2013/12/25 职场文书
污水厂厂长岗位职责
2014/01/04 职场文书
课外活动总结范文
2014/07/09 职场文书
民用住房租房协议书
2014/10/29 职场文书
2014年化妆品销售工作总结
2014/12/01 职场文书
2015年体育教学工作总结
2015/05/20 职场文书
Nginx的反向代理实例详解
2021/03/31 Servers
python 用递归实现通用爬虫解析器
2021/04/16 Python
还在手动盖楼抽奖?教你用Python实现自动评论盖楼抽奖(一)
2021/06/07 Python