什么?前端也要遍历树,还要自己获取数据?看看这几段代码吧

120 阅读3分钟

有时候,讲的文字太多反而不太理解,对于我们天天和代码打交道,多说无益,我们直接上代码。本文汇整了几个简单的前端常用树的遍历与数据获取,可根据注释和标题进行阅读,运行结果可复制到浏览器直接运行。

如何使用递归遍历一个树,并自下向上,优先输出叶子节点后再输出根节点

const tree = {
    id: 1001,
    name: '1001',
    children: [
      {
        id: 100101,
        name: '100101',
        children: [
          {id: 10010101, name: '10010101', children: []},
          {id: 10010102, name: '10010102', children: []},
        ]
      },
      {
        id: 100102,
        name: '100102',
        children: [
          {id: 10010201, name: '10010201', children: []},
          {id: 10010202, name: '10010202', children: []},
          {id: 10010203, name: '10010203', children: []}
        ]
      },
    ]
};
function getLeaf(node) {
    if(!node.children || !node.children.length) {
        console.log('叶子节点', node)
        return
    }
    for(const child of node.children){
        getLeaf(child)
    }
    console.log('父节点', node)
}
getLeaf(tree)

js中树结构根据条件查找节点返回节点路径

const tree = {
    id: 1001,
    name: '1001',
    children: [
      {
        id: 100101,
        name: '100101',
        children: [
          {id: 10010101, name: '10010101', children: []},
          {id: 10010102, name: '10010102', children: []},
        ]
      },
      {
        id: 100102,
        name: '100102',
        children: [
          {id: 10010201, name: '10010201', children: []},
          {id: 10010202, name: '10010202', children: []},
          {id: 10010203, name: '10010203', children: []}
        ]
      },
    ]
};
// tree 树
// key 查找的叶子节点key名称
// name 叶子页面的名称
// value 查找的叶子节点的值
function getPathById(tree, key, name, value){
  //定义变量保存当前结果路径
  let temppath = [];
  let tempname = [];
  try {
    function getNodePath(node) {
      temppath.push(node[key]);
      tempname.push(node[name])
      //找到符合条件的节点,通过throw终止掉递归
      if (node[key] === value) throw ('找到了');
      if (node.children && node.children.length) {
        for (let i = 0; i < node.children.length; i++) {
          getNodePath(node.children[i]);
        }
        //当前节点的子节点遍历完依旧没找到,则删除路径中的该节点
        temppath.pop();
        tempname.pop();
      } else {
        //找到叶子节点时,删除路径当中的该叶子节点
        temppath.pop();
        tempname.pop();
      }
    }
    getNodePath(tree);
  } catch (e) {
    let result = {
        path: temppath.filter(o => !!o),
        name: tempname.filter(o => !!o),
    }
    return result
  }
}

getPathById(tree, 'id', 'name', 10010202);

树的指定字段合并到一个数组,然后去重

const tree = {
    id: 1001,
    name: '1001',
    names: ['1001'],
    children: [
      {
        id: 100101,
        name: '100101',
        names: ['100101'],
        children: [
          {id: 10010101, name: '10010101', names: ['10010101'], children: []},
          {id: 10010102, name: '10010102', names: ['10010102'], children: []},
        ]
      },
      {
        id: 100102,
        name: '100102',
        names: ['100102'],
        children: [
          {id: 10010201, name: '10010201', names: ['10010201'], children: []},
          {id: 10010202, name: '10010202', names: ['10010202'], children: []},
          {id: 10010203, name: '10010203', names: ['10010203'], children: []}
        ]
      },
    ]
};
const getAllList = (tree) => {
    let list = []
    function circulTree(node) {
        list = [...list, ...(node.names || [])] // names合并到一个数组
        if(!node.children || !node.children.length) return
        for(const child of node.children) {
            circulTree(child)
        }
    }
    circulTree(tree)
    // 这里返回过滤是因为多场景兼容,因为getAllList接受的是一个对象
    // 如果names里面的是对象,根据id去重
    // return list.filter((x,i) => list.findIndex(o => o.id === x.id) === i)
    // 如果是字符串,根据每一项进行去重
    return Array.from(new Set(list))
}
getAllList(tree)