使用递归写树形结构

简介: 使用递归写树形结构

我们可以使用递归地方法写树形菜单栏,树形菜单栏的应用场景有很多,使用递归地方法可以快速地转化数据格式。使用for循环,一次只能到一层,要嵌套,并且数据不一定有几层,但递归的方法可以无限的转化数据格式。


下面我们要写一个树形结构,要求打开页面只有父级显示在页面上,子级默认隐藏,只有有子级的父级才会有下拉箭头,并且鼠标放在选中的内容上有hover效果,选中的元素会和其他的元素有明显的区别。点击父级展开下拉箭头颠倒,子级出现。


HTML中只写了一个结构:

<div class="content">
    </div>

css样式:

<style>
      * {
        margin: 0;
        padding: 0;
      }
 
      .content {
        width: 200px;
        background-color: #535d62;
      }
 
      .aline {
        width: 200px;
        height: 40px;
        display: flex;
        line-height: 40px;
      }
 
      .pic {
        width: 20px;
        height: 20px;
        margin-left: 26px;
        margin-top: 10px;
 
      }
 
      .text {
        font-size: 14px;
        color: #ffffff;
        display: flex;
        margin-left: 20px;
      }
 
      .down {
        width: 16px;
        height: 16px;
        margin-top: 15px;
        margin-left: 50px;
        /*设置所有动画的效果:0.3s 淡出效果*/
        transition: all .3s ease-out;
      }
 
      /* Hover样式 */
      .aline:hover {
        background-color: #7d7d7d;
        transition: 0.5s;
      }
 
      .aline:hover .text {
        color: #88baa7;
        transition: 0.5s;
      }
 
      .aline.selected {
        background-color: #7d7d7d;
        color: #88baa7;
      }
 
      .childs {
        display: none;
      }
 
      .down-rotate {
        transform: rotate(180deg);
        /* 可选的过渡效果 */
        transition: transform 0.3s ease;
      }
    </style>

js代码:

// 递归的数据格式转化 
      // 参数: data 表示扁平数据,一维的全部数据
      // 参数: pid 表示数据的父级id 一级数据pid=0
      // 参数: arr 数组,函数出来过后将其返回至调用函数位置,函数处理的结果
      function treeData(data, pid, arr = []) {
        // for循环 遍历数组 
        for (let i in data) {
          // 判断数据的pid是否等于父级的id
          if (data[i].pid == pid) {
            // 把数据放在arr中
            arr.push(data[i]);
            // 把子元素放在父级元素中
            arr[arr.length - 1].children = treeData(data, data[i].id)
          };
        };
        // 返回arr的值
        return arr;
      };
      // 声明变量tree_data 等于所有的父级元素
      let tree_data = treeData(arr, 0);
      console.log(tree_data);
 
      function tree_menu(data) {
        // 整个背景
        let str = '<div class="content">';
        // for循环遍历数组
        for (let i = 0; i < data.length; i++) {
 
          // 判断是否有子级
          if (data[i].children.length > 0) {
            // 当有子元素时拼接名称和下拉箭头和拼接图标
            str += `
            <div class="aline" onclick="click_show(this)">
            <img class="pic" src="${data[i].img}" alt="" /><div class="text">${data[i].name}
            <img class="down" src="img/向下箭头_小.png" alt="" />`
            str += `</div>
            </div>
            <div class="childs" style="display:none">
            ${tree_menu(data[i].children)}
            </div>`
          } else {
            // 否则只拼接名称
            str += `<div class="aline">
        <img class="pic" src="${data[i].img}" alt="" />
        <div class="text">${data[i].name}</div>
        </div>`
          };
        };
        str += '</div>'
        return str;
      };
      // 在页面内输入
      document.write(tree_menu(tree_data));
 
      // 用于跟踪当前选中的元素
      let option = null;
 
      function click_show(e) {
        // 获取下一个同级元素,即包含子项的div
        let childsDiv = e.nextElementSibling;
        // 当前被点击的.aline元素
        let alineElement = e;
 
        // 如果已经有一个元素被选中,则移除其.selected类
        if (option) {
          option.classList.remove('selected');
        };
        // 更新当前选中的元素
        option = alineElement;
 
        // 判断如果数据和数据的名称是否为childs
        if (childsDiv && childsDiv.className === 'childs') {
          // 获取当前父元素内的箭头图片
          let downArrow = e.querySelector(".down");
 
          // 切换子菜单的显示状态
          if (childsDiv.style.display === 'none') {
            // 让子级显示
            childsDiv.style.display = 'block';
            // 添加被选中的样式
            alineElement.classList.add('selected');
            // 旋转箭头
            downArrow.classList.add("down-rotate");
          } else {
            childsDiv.style.display = 'none';
            // 重置箭头
            downArrow.classList.remove("down-rotate");
          };
        };
      };
目录
相关文章
|
6月前
|
算法
落叶归根:递归思想在二叉树叶子节点类问题中的妙用
落叶归根:递归思想在二叉树叶子节点类问题中的妙用
69 1
|
5月前
|
存储 关系型数据库 MySQL
B树和B+树的区别
B树和B+树的区别
59 1
|
6月前
|
存储 数据库 索引
B树与B+树区别
B树与B+树区别
1495 1
|
6月前
|
算法 数据处理 Python
深入理解二叉树:结构、遍历和实现
深入理解二叉树:结构、遍历和实现
深入理解二叉树:结构、遍历和实现
|
存储 数据库 索引
B树和B+树的区别是什么呢?
B树和B+树的区别是什么呢?
135 0
数组转树形结构的两种实现
数组转树形结构的两种实现
52 0
|
6月前
|
存储 数据库 索引
B树与B+树的区别
B树与B+树的区别
|
6月前
|
算法
平衡二叉树的构建(递归
平衡二叉树的构建(递归
91 0
|
存储 算法 编译器
探索二叉树:结构、遍历与应用
什么是二叉树? 二叉树是一种由节点组成的层次结构,其中每个节点最多有两个子节点,分别称为左子节点和右子节点。这种结构使得二叉树在存储和搜索数据时非常高效。二叉树的一个特殊情况是二叉搜索树(Binary Search Tree,BST),它满足左子节点的值小于父节点,右子节点的值大于父节点,这种特性使得在BST中进行查找操作更加高效。
104 0
数组转树形结构(递归)
大家好,今天我将向大家分享一下数组转树形结构的方法——递归方法。