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

2023-09-20 14:53:37

理论上菜单层级可以无限多,因为是递归渲染。
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>
更多推荐

并发编程——ScheduledThreadPoolExecutor

文章目录ScheduledThreadPoolExecutor介绍ScheduledFutureTask四种方法执行任务execute方法schedule方法scheduleAtFixedRate和scheduleWithFixedDelay分析ScheduledThreadPoolExecutor介绍Schedule

力扣刷题(简单篇):两数之和、两数相加、无重复字符的最长子串

坚持就是胜利一、两数之和题目链接:https://leetcode.cn/problems/two-sum/给定一个整数数组nums和一个整数目标值target,请你在该数组中找出和为目标值target的那两个整数,并返回它们的数组下标。你可以假设每种输入只会对应一个答案。但是,数组中同一个元素在答案里不能重复出现。你

QCA组态如何科学命名?

前言(一)文献来源文献来源:[1]FurnariS,CrillyD,MisangyiVF,etal.Capturingcausalcomplexity:Heuristicsforconfigurationaltheorizing[J].AcademyofManagementReview,2021,46(4):778-7

Linux下的系统编程——线程同步(十三)

前言:在多线程编程中,如果多个线程同时访问和修改共享资源,可能会产生竞争条件和数据不一致的问题。同步机制用于协调线程之间的访问和操作,确保数据的正确性和一致性。为了避免多个线程同时访问和操作共享资源导致的问题,可以使用互斥锁(mutex)来实现线程的互斥访问。互斥锁可以保证同一时间只有一个线程访问共享资源、条件变量用于

读书笔记:多Transformer的双向编码器表示法(Bert)-2

多Transformer的双向编码器表示法BidirectionalEncoderRepresentationsfromTransformers,即Bert;第2章了解Bert模型(掩码语言模型构建和下句预测)文本嵌入模型Bert,在许多自然语言处理任务上表现优秀,本节主要包括:了解Bert,及与其他嵌入模型的区别;分

Packet Tracer中交换机的配置及Lab2实验

交换机是计算机网络中的一种网络设备,用于在局域网内传输和转发数据包。它具有数据包转发、数据包过滤、VLAN划分和端口管理等功能,能够实现高速、可靠和安全的数据传输,并支持网络的管理和控制。交换机在网络中发挥着连接终端设备和实现数据交换的重要作用。交换机的基本配置模式:模式提示符作用用户模式>只允许用户访问有限量的基本监

【Python基础】S01E03 元组

P01S03元组定义元组元组无法修改定义一个元素的元素修改元组变量方案一:关联新元组方案二:转换为列表列表是可修改的,对于处理网站的用户列表或游戏中的角色列表至关重要。然而我们有时候需要创建一系列不可修改的元素,元组可以满足这种需求。Python中,元组是不可修改的列表,名(tuple);定义元组元组看起来很像列表,但

c++ this指针与空指针调用类方法以及常函数

一、this指针说明1、c++的成员变量与成员内函数是分开存储2、每一个非静态成员函数只会诞生一份函数实例,多个同类型的队形公用的是同一份成员函数的代码3、this指向调用这一份成员函数代码的对象实例4、this是一个隐藏的指向对象实例的一个指针,无需定义直接使用即可作用1、可以区别形参与成员变量(当成员函数的形参与类

CentOS7平台命令安装Anaconda3、配置Python3开发环境

要在CentOS7上安装Anaconda3,您可以按照以下步骤进行操作:1.下载Anaconda3安装包:首先,访问Anaconda官方网站以获取最新版本的Anaconda3安装包的下载链接。可以使用wget命令来下载安装包。请确保选择适用于CentOS7的版本。wgethttps://repo.anaconda.co

1.centos7安装docker

本文目录:1.docker安装1.安装步骤2.安装是否成功校验3.docker加速配置4.helloworld来袭,验证安装是否ok2.卸载docker3.卸载较旧版本docker使用docker必备的三个官方网站:docker官网:https://www.docker.comdocker官方仓库:https://hu

SpringBoot文件上传-阿里云OSS

1.打开阿里云说明:登录阿里云账号2.点击AccessKey管理3.创建AccessKey说明:记得复制accessKeyId,accessKeySecret并保存起来4.点击对象存储OSS5.创建Bucket说明:创建储存桶6.查看SDK示例7.Java简单上传8.上传文件流说明:以上传图片为例9.copy代码说明:

热文推荐