使用递归写树形结构

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

我们可以使用递归地方法写树形菜单栏,树形菜单栏的应用场景有很多,使用递归地方法可以快速地转化数据格式。使用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");
          };
        };
      };
目录
相关文章
|
7天前
|
人工智能 运维 安全
|
5天前
|
人工智能 异构计算
敬请锁定《C位面对面》,洞察通用计算如何在AI时代持续赋能企业创新,助力业务发展!
敬请锁定《C位面对面》,洞察通用计算如何在AI时代持续赋能企业创新,助力业务发展!
|
6天前
|
机器学习/深度学习 人工智能 自然语言处理
B站开源IndexTTS2,用极致表现力颠覆听觉体验
在语音合成技术不断演进的背景下,早期版本的IndexTTS虽然在多场景应用中展现出良好的表现,但在情感表达的细腻度与时长控制的精准性方面仍存在提升空间。为了解决这些问题,并进一步推动零样本语音合成在实际场景中的落地能力,B站语音团队对模型架构与训练策略进行了深度优化,推出了全新一代语音合成模型——IndexTTS2 。
607 21
|
12天前
|
人工智能 JavaScript 测试技术
Qwen3-Coder入门教程|10分钟搞定安装配置
Qwen3-Coder 挑战赛简介:无论你是编程小白还是办公达人,都能通过本教程快速上手 Qwen-Code CLI,利用 AI 轻松实现代码编写、文档处理等任务。内容涵盖 API 配置、CLI 安装及多种实用案例,助你提升效率,体验智能编码的乐趣。
970 110
|
6天前
|
人工智能 测试技术 API
智能体(AI Agent)搭建全攻略:从概念到实践的终极指南
在人工智能浪潮中,智能体(AI Agent)正成为变革性技术。它们具备自主决策、环境感知、任务执行等能力,广泛应用于日常任务与商业流程。本文详解智能体概念、架构及七步搭建指南,助你打造专属智能体,迎接智能自动化新时代。