Javascript小案例--树形菜单(菜单数据为对象)

news2025/7/18 15:25:45

理论上菜单层级可以无限多,因为是递归渲染。
gif效果图:
在这里插入图片描述

代码

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>树形菜单</title>
</head>
<style>
  * {
    padding: 0;
    margin: 0;
    box-sizing: border-box;
    font-size: 14px;
  }

  body{
    background-color: #444;
  }
  /*侧栏菜单 */
  .aside_menu {
    position: fixed;
    min-width: 350px;
    height: 700px;
    background-color: #333;
    padding: 20px;
    border: 0;
    border-right: 3px solid #333;
    cursor: pointer;
    color: white;
    overflow: auto;
  }

  /* 菜单项 */
  .menuItem{
    margin-bottom: 5px;
    height: 30px;
    line-height: 30px;
    padding-right: 10px;
  }  
  .menuItem:hover {
    color: #333;
    background-color: #bbcaca;
  }

  /* 有子菜单的菜单项 */
  [data-child-count]::after {
    content: '<';
    opacity: 0.3;
    float: right;
  }

  /* 有子菜单的菜单项 */
  .expandable::after {
    content: '>';
    opacity: 0.3;
    float: right;
  }

  /* 子菜单折叠 */
  .collapsable {
    display: none;
  }
</style>

<body>
  <div class="aside_menu">
    <div class="menuwrraper"></div>
  </div>
  <script>
    /**
     * 菜单对象说明:
      {
        id: '0',//菜单id
        name: '菜单名',//菜单名称
        submenu: []//子菜单集合
      },
     **/
    let menuRoot = {
      id: '0',
      name: '树形菜单',
      submenu: [
        {
          id: '0',
          name: '菜单',
          submenu: []
        },
        {
          id: '0',
          name: '菜单',
          submenu: [
            {
              id: '0',
              name: '菜单',
              submenu: [
                {
                  id: '0',
                  name: '菜单',
                  submenu: []
                },
              ]
            },
          ]
        },
        {
          id: '0',
          name: '菜单',
          submenu: [
            {
              id: '0',
              name: '菜单',
              submenu: []
            },
          ]
        },
        {
          id: '0',
          name: '菜单',
          submenu: [
            {
              id: '0',
              name: '菜单',
              submenu: [
                {
                  id: '0',
                  name: '菜单',
                  submenu: [
                    {
                      id: '0',
                      name: '菜单',
                      submenu: [
                        {
                          id: '0',
                          name: '菜单',
                          submenu: [
                            {
                              id: '0',
                              name: '菜单',
                              submenu: [
                                {
                                  id: '0',
                                  name: '菜单',
                                  submenu: [
                                    {
                                      id: '0',
                                      name: '菜单',
                                      submenu: [
                                        {
                                          id: '0',
                                          name: '菜单',
                                          submenu: [
                                            {
                                              id: '0',
                                              name: '菜单',
                                              submenu: [
                                                {
                                                  id: '0',
                                                  name: '菜单',
                                                  submenu: []
                                                },
                                              ]
                                            },
                                          ]
                                        },
                                      ]
                                    },
                                  ]
                                },
                              ]
                            },
                          ]
                        },
                      ]
                    },
                  ]
                },
              ]
            },
          ]
        },
        {
          id: '0',
          name: '菜单',
          submenu: [
            {
              id: '0',
              name: '菜单',
              submenu: [
                {
                  id: '0',
                  name: '菜单',
                  submenu: [
                    {
                      id: '0',
                      name: '菜单',
                      submenu: [
                        {
                          id: '0',
                          name: '菜单',
                          submenu: [
                            {
                              id: '0',
                              name: '菜单',
                              submenu: [
                                {
                                  id: '0',
                                  name: '菜单',
                                  submenu: [
                                    {
                                      id: '0',
                                      name: '菜单',
                                      submenu: [
                                        {
                                          id: '0',
                                          name: '菜单',
                                          submenu: [
                                            {
                                              id: '0',
                                              name: '菜单',
                                              submenu: [
                                                {
                                                  id: '0',
                                                  name: '菜单',
                                                  submenu: []
                                                },
                                              ]
                                            },
                                          ]
                                        },
                                      ]
                                    },
                                  ]
                                },
                              ]
                            },
                          ]
                        },
                      ]
                    },
                  ]
                },
              ]
            },
          ]
        },
        {
          id: '0',
          name: '菜单',
          submenu: [
            {
              id: '0',
              name: '菜单',
              submenu: [
                {
                  id: '0',
                  name: '菜单',
                  submenu: [
                    {
                      id: '0',
                      name: '菜单',
                      submenu: [
                        {
                          id: '0',
                          name: '菜单',
                          submenu: [
                            {
                              id: '0',
                              name: '菜单',
                              submenu: [
                                {
                                  id: '0',
                                  name: '菜单',
                                  submenu: [
                                    {
                                      id: '0',
                                      name: '菜单',
                                      submenu: [
                                        {
                                          id: '0',
                                          name: '菜单',
                                          submenu: [
                                            {
                                              id: '0',
                                              name: '菜单',
                                              submenu: [
                                                {
                                                  id: '0',
                                                  name: '菜单',
                                                  submenu: []
                                                },
                                              ]
                                            },
                                          ]
                                        },
                                      ]
                                    },
                                  ]
                                },
                              ]
                            },
                          ]
                        },
                      ]
                    },
                  ]
                },
              ]
            },
          ]
        },
      ]
    }
    /**
     * menuWrraper-菜单最外层包装盒子,用于包裹当前菜单项及当前菜单项的子菜单
     * level-菜单层级,默认为L0,依次为L1,L2,...
     * menuData-菜单对象
     * paddingLeft-菜单左内边距,会根据菜单层级Level依次增加paddingIncrement
     * paddingIncrement-默认为20,单位为 px
     * */
    function renderMenu(menuData, menuWrraper, level = 0, paddingLeft = 0, paddingIncrement = 20) {
      if (menuData != null) {
        // 0.创建当前菜单
        const menuItem = document.createElement('div')
        // 0.1 添加菜单id
        menuItem.dataset.id = menuData.id
        // 0.2 添加菜单层级L0,L1,L2,...
        menuItem.classList.add(`L${level}`)
        // 0.3 用于控制鼠标 hover效果
        menuItem.classList.add('menuItem')
        // 0.4 菜单左内边距
        menuItem.style.paddingLeft = `${paddingLeft}px`
        // 0.5 菜单内容
        menuItem.innerHTML = `<span>${menuData.name}</span>`
        // 0.6 ****追加当前菜单盒子
        menuWrraper.appendChild(menuItem)
        const submenu = menuData.submenu
        if (submenu.length > 0) {// 如果当前菜单有子菜单,则
          // 1. 为当前菜单追加一个属性,表示其有 子菜单
          // menuItem.dataset.hasChild = 1
          menuItem.dataset.childCount = submenu.length
          // 2. 为当前菜单注册点击事件,可折叠展开子菜单、切换折叠展开图标
          menuItem.addEventListener('click', () => {
            // 2.1 ****用于CSS渲染可展开的最右侧小图标:‘<’ 或者 ‘>’
            menuItem.classList.toggle('expandable')
            // 2.2 ****用于控制子菜单折叠与展开,也即控制submenuWrraper的dispaly属性为‘none’或者‘block’
            menuItem.nextElementSibling.classList.toggle('collapsable')
          })
          // 3. 菜单层级加1
          level++;
          // 4. 左边距增加
          paddingLeft += paddingIncrement
          // 5. 创建子菜单包装盒子
          const submenuWrraper = document.createElement('div')
          // 7.*****追加子菜单盒子,追加这个盒子的原因是 2.2
          menuWrraper.appendChild(submenuWrraper)
          // 6.*****循环当前菜单的子菜单
          for (let i = 0; i < submenu.length; i++) {
            // 6.1 ****递归渲染每一项子菜单
            renderMenu(submenu[i], submenuWrraper, level, paddingLeft)
          }
          
        }
      }
    }
    // 调用菜单渲染函数生成页面数据
    renderMenu(menuRoot, document.querySelector('.menuwrraper'))
    // 渲染完毕后,释放菜单数据
    menuRoot = null
  </script>
</body>

</html>

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

RHCE---Linux的计划任务

文章目录 前言一、pandas是什么&#xff1f;二、使用步骤 1.引入库2.读入数据总结 前言 如果想要让自己设计的备份程序可以自动地在系统下面运行&#xff0c;而不需要手动来启动它&#xff0c;这是该如何处理&#xff1f;这些任务可以分为【单一】任务和【循环】任务&#xff0…

集简云票税通,高效、管理销项发票,满足多样化开票需求

随着数字化时代的到来&#xff0c;传统的纸质发票已经逐渐被电子发票所替代。然而&#xff0c;对于许多企业来说&#xff0c;管理和开具大量的销项发票仍然是一项繁琐的任务&#xff1a; 票税处理成本高&#xff0c;手工开票效率低。部分企业手工开票量大&#xff0c;耗费大量财…

问题:conda删除虚拟环境,报错no package names supplied

用conda 用 conda remove -n ScratchDet_20200114 删除虚拟 环境ScratchDet_20200114时报错 conda remove -n ScratchDet_20200114CondaValueError: no package names supplied,try "conda remove -h" for more details 解决方法&#xff0c;用下面的命令 conda env…

C++——vector(3)

作者&#xff1a;几冬雪来 时间&#xff1a;2023年9月20日 内容&#xff1a;C部分——vector内容讲解 目录 前言&#xff1a; erase&#xff1a; erase和insert总结&#xff1a; resize&#xff1a; 深拷贝&#xff1a; 赋值&#xff1a; 结尾&#xff1a; 前言&…

CentOS7在磁盘 Disk /dev/vdb 格式化为xfs, 创建逻辑卷saas,并挂载到/home/saas

CentOS7在磁盘 Disk /dev/vdb 格式化为xfs&#xff0c; 创建逻辑卷saas&#xff0c;并挂载到/home/saas CentOS7在磁盘 Disk /dev/vdb 格式化为xfs&#xff0c; 创建逻辑卷saas&#xff0c;并挂载到/home/saasCentOS7在磁盘 Disk /dev/vdb 格式化为xfs&#xff0c;并挂载到/ho…

关于安卓SVGA浅尝(一)svgaplayer库的使用

关于安卓SVGA浅尝&#xff08;一&#xff09;使用 相关链接 SVGA官网 SVGA-github说明文档 背景 项目开发&#xff0c;都会和动画打交道&#xff0c;动画的方案选取&#xff0c;就有很多选择。如Json动画&#xff0c;svga动画&#xff0c;gif等等。各有各的优势。目前项目中…

什么是浏览器的同源策略(same-origin policy)?它对AJAX有什么影响?

聚沙成塔每天进步一点点 ⭐ 专栏简介⭐ 浏览器的同源策略&#xff08;Same-Origin Policy&#xff09;⭐ 同源策略对AJAX的影响⭐ 写在最后 ⭐ 专栏简介 前端入门之旅&#xff1a;探索Web开发的奇妙世界 欢迎来到前端入门之旅&#xff01;感兴趣的可以订阅本专栏哦&#xff01;…

Mybatis 映射器中使用@InsertProvider,@UpdateProvider,@DeleteProvider,@SelectProvider

上一篇我们介绍了在Mybatis映射器的映射方法中使用Param接收多个参数&#xff1b;本篇我们继续介绍如何在Mybatis的映射器中使用动态SQL。 如果您对Mybatis映射器的映射方法中使用Param接收多个参数不太了解&#xff0c;建议您先进行了解后再阅读本篇&#xff0c;可以参考&…

iphone的safari浏览器实现全屏的pwa模式,并修改顶部状态栏背景颜色

要想修改顶部背景颜色&#xff0c;需要用到这个属性&#xff1a;content就是你要设置的颜色 <!-- 状态栏的背景色 --><meta name"theme-color" content"#f8f8f8" /> 然后再加上下面的设置&#xff1a; <!-- 网站开启对 web app 程序的支持…

DAZ To UMA⭐一.DAZ使用简介 / 设置DAZ导出的内容 / 获取模型纹理贴图

文章目录 🟥 DAZ快捷键🟧 DAZ界面介绍🟩 设置DAZ导出的内容1️⃣ 找到要导出的参数名称2️⃣ 打开导出面板3️⃣ 设置导出规则举例 : 导出身体Assets🟦 获取模型纹理贴图🟥 DAZ快捷键 移动物体:ctrl+alt+鼠标左键 旋转物体:ctrl+alt+鼠标右键 导入模型:双击左侧模型…

修改接口,字段的内容允许清空,避免歧义,参数校验:@NotNull

1. 问题描述 修改接口&#xff0c;字段的内容允许清空&#xff0c;是否应该做参数校验&#xff1f;如何做参数校验&#xff1f; 2. 说明 2.1. 需要对字段进行校验。 因为不校验&#xff0c;字段可能不传&#xff0c;或者字段的值为null&#xff1b;这样无法判断出&#xff…

Nginx是如何支持百万并发的?

通过源码分析Nginx的整体架构,以及进程模型。Nginx是一个免费的,开源的,高性能的HTTP服务器和反向代理。以其高性能,稳定性,丰富的功能,简单的配置和低资源消耗而闻名。Nginx是一个Web服务器,也可以用作负载均衡器和HTTP缓存。 很多高知名度的网站都使用Nginx,比如:N…

【线性代数】为什么 AA* = |A|E

A A ∗ 矩阵相乘&#xff0c;刚好是行列式展开的定义 AA*矩阵相乘&#xff0c;刚好是行列式展开的定义 AA∗矩阵相乘&#xff0c;刚好是行列式展开的定义 矩阵提取一个因子 ∣ A ∣ &#xff0c;所有元素需要除 ∣ A ∣ 矩阵提取一个因子 |A|&#xff0c;所有元素需要除 |A| 矩…

生信分析Python实战练习 9 | 视频27

开源生信 Python教程 生信专用简明 Python 文字和视频教程 源码在&#xff1a;https://github.com/Tong-Chen/Bioinfo_course_python 目录 背景介绍 编程开篇为什么学习Python如何安装Python如何运行Python命令和脚本使用什么编辑器写Python脚本Python程序事例Python基本语法 数…

视频编辑软件Premiere Pro 2022 mac(pr2023)v22.6.2中文功能

​Premiere Pro 2022 mac可以帮助用户对各种视频进行剪辑、旋转、分割、合并、字幕添加、背景音乐等基础的处理&#xff0c;pr2022还能帮助用户进行视频颜色校正、颜色分级、稳定镜头、调整层、更改片段的持续时间和速度、效果预设等操作。 Premiere Pro 22.1.2 包含版本 22.1.…

算法讨论题 —— Java实现两数之和

给定一个整数数组和一个目标值&#xff0c;找出数组中和为目标值的两个数。 你可以假设每个输入只对应一种答案&#xff0c;且同样的元素不能被重复利用。即:每个index上的数字只能用一次。 示例 给定 nums [2, 7, 11, 15], target 9 因为 nums[0] nums[1] 2 7 9 所以返…

汽车电子相关术语

SOA SOA&#xff08;Service-Oriented Architecture&#xff0c;面向服务的架构&#xff09;是一种在计算机环境中设计、开发、部署和管理离散模型的方法。是由Garnter1996年提出的概念&#xff0c;将应用程序的不同功能单元&#xff08;称为服务&#xff09;进行拆分&#xf…

高级运维学习(九)块存储、文件系统存储和对象存储的实现

块存储基础 块设备存取数据时&#xff0c;可以一次存取很多。字符设备只能是字符流 [rootceph1 ~]# ll /dev/sda brw-rw---- 1 root disk 8, 0 Dec 12 13:15 /dev/sda # b表示block&#xff0c;块设备[rootceph1 ~]# ll /dev/tty crw-rw-rw- 1 root tty 5, 0 Dec 12 13:31 /d…

springboot和vue:二、springboot特点介绍+热部署热更新

springboot特点介绍 能够使用内嵌的Tomcat、Jetty服务器&#xff0c;不需要部署war文件。提供定制化的启动器Starters&#xff0c;简化Maven配置&#xff0c;开箱即用。纯Java配置&#xff0c;没有代码生成&#xff0c;也不需要XML配置。提供了生产级的服务监控方案&#xff0…

git之撤销工作区的修改和版本回溯

有时候在工作区做了一些修改和代码调试不想要了,可如下做 (1)步骤1:删除目录代码,确保.git目录不能修改 (2)git log 得到相关的commit sha值 可配合git reflog 得到相要的sha值 (3)执行git reset --hard sha值,可以得到时间轴任意版本的代码 git reset --hard sha值干净的代…