• 原生js生成无限级树形菜单


    设计思路:

    要生成菜单的源数据往往是一个树形数据结构(若不是也可以转换成树形结构),(那我们一起写博客吧)因为源数据结构和目标菜单结构都为树形结构,所以其实我们要做的就是数据结构的转译,即将js树形数据转换为 ul, li 拼接成的树形菜单。在这里我们通过树的深度优先遍历方式来完成这次转义操作。

    结构(转义)映射关系说明:

    迭代树形数据时,树形结构数据的每个同层级别的每条数据转换成一个 LI标签包裹的菜单项(添加class为menu-item标识),当遇到childrens项时,当前项数据用 LI 标签包裹(添加class为menu标识),同时在该LI标签后面添加UL标签作为下一级菜单包裹项,迭代childrens作为上述UL标签的子菜单项,对childrens子元素的操作同上述描述的操作。

    简单总结就是树的每条数据都转换为LI标签内容,每个childrens都转换为UL标签。

    以下我们来完成对上述描述代码实现

    1,js树形数据

      1 var menuList = [
      2     {
      3         name: '音程比较',
      4         childrens: [
      5             {
      6                 name: '比较纯音程',
      7             },
      8             {
      9                 name: '比较不完全和协音程',
     10             },
     11             {
     12                 name: '比较不协和音程',
     13                 childrens: [
     14                     {
     15                         name: '大二度&小七度-上行',
     16                         intervalId: 112,
     17                         questionType: "bj",
     18                     },
     19                     {
     20                         name: '大二度&小七度-下行',
     21                         intervalId: 113,
     22                         questionType: "bj",
     23                     },
     24                 ],
     25             },
     26             {
     27                 name: '比较跨两个八度的复合音程',
     28             }
     29         ]
     30     },
     31     {
     32         name: '音程辨认',
     33         childrens: [
     34             {
     35                 name: '辨认小二度和大二度音程',
     36                 childrens: [
     37                     {
     38                         name: '分辨小二度和大二度音程-上行',
     39                         intervalId: 1,
     40                         questionType: "br",
     41                     },
     42                     {
     43                         name: '分辨小二度和大二度音程-下行',
     44                         intervalId: 2,
     45                         questionType: "br",
     46                     },
     47                     {
     48                         name: '分辨小二度和大二度音程-和声',
     49                         intervalId: 3,
     50                         questionType: "br",
     51                     },
     52                     {
     53                         name: '分辨小二度和大二度音程-上行下行',
     54                         intervalId: 4,
     55                         questionType: "br",
     56                     },
     57                     {
     58                         name: '分辨小二度和大二度音程-上行和声',
     59                         intervalId: 5,
     60                         questionType: "br",
     61                     },
     62                     {
     63                         name: '分辨小二度和大二度音程-下行和声',
     64                         intervalId: 6,
     65                         questionType: "br",
     66                     }
     67                 ]
     68             },
     69             {
     70                 name: '辨认小三度和大三度的音程',
     71                 childrens: [
     72                     {
     73                         name: "分辨小三度和大三度音程-上行",
     74                         intervalId: 7,
     75                         questionType: "br",
     76                     },
     77                     {
     78                         name: "分辨小三度和大三度音程-下行",
     79                         intervalId: 8,
     80                         questionType: "br",
     81                     },
     82                     {
     83                         name: "分辨小三度和大三度音程-和声",
     84                         intervalId: 9,
     85                         questionType: "br",
     86                     },
     87                     {
     88                         name: "分辨小三度和大三度音程-上行下行",
     89                         intervalId: 10,
     90                         questionType: "br",
     91                     },
     92                     {
     93                         name: "分辨小三度和大三度音程-上行和声",
     94                         intervalId: 11,
     95                         questionType: "br",
     96                     },
     97                     {
     98                         name: "分辨小三度和大三度音程-下行和声",
     99                         intervalId: 12,
    100                         questionType: "br",
    101                     }
    102                 ]
    103             },
    104         ]
    105     },
    106 ]
    treeData

    2,迭代生成树形菜单

     1         // 生成dom tree
     2         function generateDomTree(treeData, config = {
     3             label: 'name',
     4             childrens: 'childrens'
     5         }) {
     6             var label = config.label // 要显示的字段名
     7             var childrensKey = config.childrens // 子节点字段名
     8             var container = generateDomEle('ul')
     9             /* 
    10              fragment 菜单容器
    11              menuList 待遍历菜单
    12              show 展开菜单
    13             */
    14             function deep(fragment, menuList, show) {
    15                 for (const menu of menuList) {
    16                     var liDom = generateDomEle('li', {
    17                         innerText: menu[label]
    18                     })
    19                     var childrens = menu[childrensKey]
    20                     // 子节点存在
    21                     if (childrens && childrens.length) {
    22                         fragment.appendChild(liDom) // 插入节点
    23                         var urlDom = generateDomEle('ul') // 生成下一级菜单
    24                         liDom.classList.add('menu') // 添加菜单标识
    25                         if (!show) {
    26                             // 关闭菜单
    27                             liDom.classList.add('close')
    28                         }
    29                         fragment.appendChild(urlDom)
    30 
    31                         deep(urlDom, childrens, show) // 迭代
    32                     } else {
    33                         liDom.classList.add('menu-item') // 添加菜单项标识
    34                         fragment.appendChild(liDom)
    35                     }
    36                 }
    37             }
    38             deep(container, treeData, false)
    39             return container
    40         }
    generateDomTree

    3,给菜单添加点击展开关闭操作

     1         var container = generateDomTree(treeData)
     2         container.addEventListener('click', function (e) {
     3             var target = e.target
     4             // 点中 li
     5             if (target.tagName == 'LI') {
     6                 // 点中菜单
     7                 if (target.classList.contains('menu')) {
     8                     target.classList.toggle('close') // 如果关闭则展开,展开则关闭
     9                 } else {
    10                     //做你想做的
    11                 }
    12             }
    13         }, false)
    open or close

    4,相关代码解释说明

    4-1,代码中用到的自定义方法代码片段

    1 // 生成dom节点
    2 function generateDomEle(tagName, property) {
    3     var property = property || {}
    4     var ele = document.createElement(tagName)
    5     for (var key in property) {
    6         ele[key] = property[key]
    7     }
    8     return ele
    9 }
    snippet code

    4-2,效果图

    4-3,生成的dom结构

    @萍2樱释 ღ( ´・ᴗ・` )

    打不死的小强
  • 相关阅读:
    目标跟踪学习笔记1
    求职笔记
    Pycharm使用问题小结-002
    Pycharm使用问题小结-001
    Python基础练习-004-百变乘法表
    Python基础练习-003-求100-999之间所有的水仙花数
    Python基础练习-002-求1000以内的完全数
    Python基础练习-001-猜数字小游戏
    java.io.FileNotFoundException: rmi_keystore.jks (No such file or directory)(转)
    Jmeter
  • 原文地址:https://www.cnblogs.com/mggahui/p/13381372.html
Copyright © 2020-2023  润新知