树状菜单(利用映射-bootstrap+jQuery实现折叠功能)

效果(默认全部展开):
在这里插入图片描述

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
    <link
      rel="stylesheet"
      href="https://cdn.staticfile.org/twitter-bootstrap/3.3.7/css/bootstrap.min.css"
    />
    <script src="https://cdn.staticfile.org/jquery/2.1.1/jquery.min.js"></script>
    <script src="https://cdn.staticfile.org/twitter-bootstrap/3.3.7/js/bootstrap.min.js"></script>
  </head>
  <style>
    /* 树状菜单 */
    #ulShow {
      height: 100%;
    }

    #ulShow > .list-group {
      color: #fff;
      margin: 0;
      height: 40px;
      line-height: 40px;
      margin: 0;
      list-style: none;
    }

    /* 一级菜单 */
    #ulShow > .list-group > .list-group {
      margin: 0;
      padding-left: 20px;
      background-color: #2d363f;
    }

    #ulShow > .list-group > .collapse > .list-group {
      margin: 0;
    }

    /* 动画进行时的样式设置,要和动画结束时的样式保持一致 */
    #ulShow > .list-group > .collapse > .list-group > .list-group-item,
    #ulShow > .list-group .collapsing .list-group-item {
      display: flex;
      align-items: center;
      padding: 0;
      padding-left: 40px;
      background-color: #1e2d3b;
      border: 0;
    }

    #ulShow > .list-group > .collapse > .list-group > .list-group-item a,
    #ulShow > .list-group .collapsing .list-group-item a {
      text-decoration: none;
      color: #fff;
    }

    #ulShow > .list-group > .collapse > .list-group > .list-group-item:hover,
    #ulShow > .list-group .collapsing .list-group-item:hover {
      background: #2d363f;
      cursor: pointer;
    }

    #ulShow > .list-group > .collapse > .list-group > .list-group-item:hover a,
    #ulShow > .list-group .collapsing .list-group-item:hover a {
      color: lightblue;
    }

    #ulShow > .list-group .collapsing {
      transition: height 0.5s ease;
      /* 修改为你想要的持续时间和缓动函数 */
      /* 动画加载时会有一个向下的高度占位 */
      /* background-color: red; */
    }
  </style>
  <body>
    <div id="ulShow"></div>
    <script>
      const menuArray = [
        { id: 1, pageName: "用户管理", pid: 0 },
        { id: 2, pageName: "图书管理", pid: 0 },
        { id: 3, pageName: "销售管理", pid: 0 },
        { id: 4, pageName: "借阅管理", pid: 0 },
        { id: 5, pageName: "系统设置", pid: 0 },
        { id: 6, pageName: "用户类型管理", pid: 1 },
        { id: 7, pageName: "用户信息管理", pid: 1 },
        { id: 8, pageName: "新增用户", pid: 1 },
        { id: 9, pageName: "图书类型管理", pid: 2 },
        { id: 10, pageName: "图书管理", pid: 2 },
        { id: 11, pageName: "入库管理", pid: 3 },
        { id: 12, pageName: "出库管理", pid: 3 },
        { id: 13, pageName: "借书管理", pid: 4 },
        { id: 14, pageName: "还书管理", pid: 4 },
        { id: 15, pageName: "退出", pid: 5 },
      ];
      function showMenu(menuArray) {
        // 创建一个映射对象,用于存储菜单项及其子菜单项,map是计算结束后返回的值,是下一次调用回调时的第一个参数;item是当前值
        const itemMap = menuArray.reduce((map, item) => {
          // 将每个菜单项添加到映射中,并初始化其子菜单项数组
          /*
			在这段代码中,...item 用于对象展开(Object Spreading)是有效的,因为它正确地复制了 item 对象的所有可枚举属性到新创建的对象中。
			对象展开(Object Spreading)与浅拷贝(Shallow Copy)是相关的概念。在这段代码中,...item 进行的操作实际上是一个浅拷贝。
			浅拷贝是指创建一个新对象,并将原始对象的所有非静态属性的值复制到新对象中。如果这些属性值是基本类型(如数字、字符串、布尔值),则直接复制值;如果属性值是引用类型(如对象、数组),则复制的是内存中的地址,而不是实际的对象或数组。这意味着新对象和原始对象仍然共享对这些引用类型属性的引用。
			在对象展开中,...item 创建了一个新对象,并将 item 的所有可枚举属性复制到新对象中。由于这些属性是按值复制的,如果属性是基本类型,它们将被直接复制;如果属性是引用类型(例如,另一个对象或数组),则复制的是对这个引用类型值的引用,而不是实际的对象或数组本身。因此,对象展开在这种情况下执行的是一个浅拷贝。
			这段代码中的 subItems: [] 创建了一个新的空数组,并将其赋值给新对象的 subItems 属性。这是对新数组的一个独立引用,它不会影响原始 item 对象中的任何属性或数组。
			因此,当你在这段代码中使用 ...item 时,你正在创建一个新对象,该对象包含原始 item 对象的所有属性的浅拷贝,并且添加了一个新的 subItems 属性,该属性指向一个全新的数组。这样,每个 item 在 itemMap 中都有一个独立的、不与其他 item 共享的 subItems 数组。
		  */
          map[item.id] = { ...item, subItems: [] };

          // 如果菜单项没有父级(顶级菜单项),则标记为顶级
          if (item.pid === 0) {
            map[item.id].topLevel = true;
          } else {
            // 如果菜单项有父级,则将其添加到父级菜单项的子菜单项数组中
            const parentId = item.pid;
            if (map[parentId]) {
              map[parentId].subItems.push(item);
            }
          }

          return map;
        }, {});
        console.log(itemMap, "itemMap");

        // 从映射中提取所有顶级菜单项,返回一个新数组
        const topLevelItems = Object.values(itemMap).filter(
          (item) => item.topLevel
        );

        // 构建顶级菜单项的 HTML 内容
        const listGroupContent = topLevelItems
          .map((topItem) => {
            let subItemsHtml = "";

            // 如果顶级菜单项有子菜单项,则构建子菜单项的 HTML 内容
            if (topItem.subItems.length > 0) {
              // 为子菜单项创建一个唯一的 collapse ID
              const collapseId = `collapse-${topItem.id}`;

              // 构建子菜单项的列表组,并将其包装在一个 collapse 元素中
              subItemsHtml =
                `<div class="collapse" id="${collapseId}">` +
                `<ul class="list-group list-group-flush">` +
                topItem.subItems
                  .map(
                    (subItem) =>
                      // 将子菜单项转换为 a 标签,并设置 href 属性
                      `<li class="list-group-item subItem" οnclick="handleSubItem('${subItem.pageName}')"><a href="#">${subItem.pageName}</a></li>`
                  )
                  .join("") +
                `</ul>` +
                `</div>`;

              // 创建折叠触发器的按钮,并设置 data-target 属性以指向相应的 collapse 元素
              const triggerButton = `<div class="list-group"  data-toggle="collapse" data-target="#${collapseId}" aria-expanded="false" aria-controls="${collapseId}">${topItem.pageName}</div>`;

              // 返回顶级菜单项的 HTML 内容,包括折叠触发器和子菜单项
              return triggerButton + subItemsHtml;
            } else {
              // 如果顶级菜单项没有子菜单项,则只创建一个 a 标签
              return `<li class="list-group-item"><a href="#">${topItem.pageName}</a></li>`;
            }
          })
          .join("");

        // 清空 ulShow 元素的内容,并添加新构建的列表组内容
        $("#ulShow")
          .empty()
          .append(`<ul class="list-group">${listGroupContent}</ul>`);

        // 初始化所有 collapse 元素以启用折叠功能
        $(".collapse").collapse();
      }

      function handleSubItem(pageName) {
        console.log(pageName, "pageName");
      }

      $(".subItem").on("click", function (pageName) {
        handleSubItem(pageName);
      });
      window.onload = function () {
        showMenu(menuArray);
      };
    </script>
  </body>
</html>

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/385119.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

一、Docker部署MySQL

Docker部署MySQL 一、安装Docker二、拉取MySQL镜像1.选择拉取版本2.拉取镜像 三、启动MySQL1.确定好挂载目录2.启动3.查看是否启动4.开启远程访问权限 一、安装Docker 安装教程&#xff1a;https://qingsi.blog.csdn.net/article/details/131270071 二、拉取MySQL镜像 1.选择…

【C语言】实现双向链表

目录 &#xff08;一&#xff09;头文件 &#xff08;二&#xff09; 功能实现 &#xff08;1&#xff09;初始化 &#xff08;2&#xff09;打印链表 &#xff08;3&#xff09; 头插与头删 &#xff08;4&#xff09;尾插与尾删 &#xff08;5&#xff09;指定位置之后…

html的格式化标签和图片(img)标签

格式化标签 加粗: strong标签和b标签倾斜: em标签和i标签删除线: del标签和s标签下划线: ins标签和u标签 <strong>stong 加粗</strong><b>b 加粗</b><em>倾斜</em><i>倾斜</i><del>删除线</del><s>删除线…

nodejs学习计划--(十)会话控制及https补充

一、会话控制 1.介绍 所谓会话控制就是 对会话进行控制 HTTP 是一种无状态的协议&#xff0c;它没有办法区分多次的请求是否来自于同一个客户端&#xff0c; 无法区分用户 而产品中又大量存在的这样的需求&#xff0c;所以我们需要通过 会话控制 来解决该问题 常见的会话控制…

论文阅读:GamutMLP A Lightweight MLP for Color Loss Recovery

这篇文章是关于色彩恢复的一项工作&#xff0c;发表在 CVPR2023&#xff0c;其中之一的作者是 Michael S. Brown&#xff0c;这个老师是加拿大 York 大学的&#xff0c;也是 ISP 领域的大牛&#xff0c;现在好像也在三星研究院担任兼职&#xff0c;这个老师做了很多这种类似的工…

苹果Mac键盘如何将 F1 到 F12 取消按Fn

苹果电脑安装了Win10操作系统之后&#xff0c;F1到F12用不了怎么办的解决方法。本文将介绍一些解决方法&#xff0c;帮助您解决无法使用F1到F12功能键的问题。 使用 Mac系统的人都知道&#xff0c;Mac系统默认是没有开启 F1-F12 的使用的&#xff0c;平时我们使用的系统都可以使…

线性时间非比较类排序之基数排序

基数排序 基数排序是桶排序的扩展&#xff0c;因此又称“桶子法”&#xff0c;它是通过键值的部分信息&#xff0c;将要排序的元素分配至某些“桶”中&#xff0c;以达到排序的作用。 1. 算法思想 将各元素按位数切割成不同的数字&#xff0c;然后分别根据每个位数的比较结果…

在线问诊系统设计与实现的经验总结与整理

随着互联网技术的快速发展&#xff0c;在线问诊服务作为一种新兴的医疗服务模式&#xff0c;正逐渐受到人们的关注和使用。本文将介绍在线问诊系统的设计原则和关键组件&#xff0c;以及如何实现一个安全、高效和可扩展的在线医疗服务平台。 内容&#xff1a; 1. 引言 - 在…

Vulnhub靶场 DC-8

目录 一、环境搭建 二、信息收集 1、主机发现 2、指纹识别 三、漏洞复现 1、SQL注入 sqlmap工具 2、dirsearch目录探测 3、反弹shell 4、提权 exim4 5、获取flag 四、总结 一、环境搭建 Vulnhub靶机下载&#xff1a; 官网地址&#xff1a;https://download.vulnhub.com/dc/DC-…

Python算法题集_合并K个升序链表

Python算法题集_合并K个升序链表 题23&#xff1a;合并K个升序链表1. 示例说明2. 题目解析- 题意分解- 优化思路- 测量工具 3. 代码展开1) 标准求解【双层循环】2) 改进版一【列表排序】3) 改进版二【堆排序】4) 改进版三【分区海选】 4. 最优算法 本文为Python算法题集之一的代…

论文介绍 FreeControl: 无需额外训练实现文本到图像的空间操控!

论文介绍 FreeControl: 无需额外训练实现文本到图像的空间操控&#xff01; 论文介绍 FreeControl: Training-Free Spatial Control of Any Text-to-Image Diffusion Model with Any Condition 关注微信公众号: DeepGo 项目地址&#xff1a;https://genforce.github.io/freeco…

【Java程序设计】【C00266】基于Springboot的超市进存销管理系统(有论文)

【Java程序设计】【C00266】基于Springboot的超市进存销管理系统&#xff08;有论文&#xff09; 项目简介项目获取开发环境项目技术运行截图 项目简介 这是一个基于Springboot的超市进销存系统 本系统分为登录注册模块、管理员功能模块以及员工功能模块。 登录注册模块&#…

Java学习18-- Override方法重写【★】

重点&#xff1a;super类 & 方法重写 ★看不明白多看几遍&#xff0c;记住static优先级>>高于override 重写Override methods★ 重写Override&#xff1a;child class可以覆盖father class中的method&#xff0c;即子类child class和父类father class有相同名称、…

如何部署一个高可用的 Linux 集群?

部署一个高可用的 Linux 集群需要经过多个步骤和考虑因素。以下是一个简要的指南&#xff0c;帮助您了解如何部署一个高可用的 Linux 集群&#xff1a; 确定需求和目标&#xff1a;在开始部署之前&#xff0c;您需要明确高可用性的定义和目标。对于一些组织而言&#xff0c;高…

鸿蒙开发第3篇__大数据量的列表加载性能优化

列表 是最常用到的组件 一 ForEach 渲染控制语法————Foreach Foreach的作用 遍历数组项&#xff0c;并创建相同的布局组件块在组件加载时&#xff0c; 将数组内容数据全部创建对应的组件内容&#xff0c; 渲染到页面上 const swiperImage: Resource[] {$r("app.me…

2024春晚纸牌魔术原理----环形链表的约瑟夫问题

一.题目及剖析 https://www.nowcoder.com/practice/41c399fdb6004b31a6cbb047c641ed8a?tabnote 这道题涉及到数学原理,有一般公式,但我们先不用公式,看看如何用链表模拟出这一过程 二.思路引入 思路很简单,就试创建一个单向循环链表,然后模拟报数,删去对应的节点 三.代码引…

数据库管理-第150期 Oracle Vector DB AI-02(20240212)

数据库管理150期 2024-02-12 数据库管理-第150期 Oracle Vector DB & AI-02&#xff08;20240212&#xff09;1 LLM2 LLM面临的挑战3 RAG4 向量数据库LLM总结 数据库管理-第150期 Oracle Vector DB & AI-02&#xff08;20240212&#xff09; 作者&#xff1a;胖头鱼的鱼…

LeetCode:69.x的平方根

嗨嗨嗨&#xff0c;二分又来了&#xff0c;淦它&#xff0c; 这个题官解是&#xff0c;C函数法&#xff0c;二分&#xff0c;和牛顿迭代法&#xff08;暂且搁置&#xff09;&#xff0c; 当然还有暴力&#xff08;不必讨论&#xff0c;就从0开始一个一个试&#xff09;&#…

2.11日学习打卡----初学RocketMQ(二)

2.11日学习打卡 一. RocketMQ整合springboot 首先配置pom.xml文件 <dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><scope>annotationProcessor</scope></dependency><dependency>…

服装效果图为何要用云渲染100?渲染100邀请码1a12

服装行业是充满创意和竞争的领域&#xff0c;而服装效果图是其中重要一环&#xff0c;以前效果图都是本地渲染&#xff0c;现在越来越多的设计师转向云渲染&#xff0c;以国内最专业的平台渲染100为例&#xff0c;云渲染有以下好处&#xff1a; 1、提高工作效率 设计师可以利用…