【问题标题】:How to make menu and submenus recursively in JavaScript?如何在 JavaScript 中递归地制作菜单和子菜单?
【发布时间】:2019-09-09 15:53:21
【问题描述】:

我想为渲染导航菜单和子菜单制作递归和动态函数

我有 JSON 对象数组,其中每个对象都是菜单项,菜单项可以有子菜单,子菜单也可以有子子菜单....我想你理解我的逻辑。

目前每个对象都有可选的标题和子菜单对象。

JSON 对象

[
{
    title: "menu 1"
    submenus: [
        {
            title: "sub menu1"
        },
        {
            title: "sub menu2"
            submenus: [
                {
                    title: "subsub menu1"
                    submenus: [
                        {
                            title: "susubsub menu1"
                        }
                    ]
                },
                {
                    title: 'subsub menu2"
                }
            ]
        }
    ]
},
{
    title: "menu 2"
}]

知道怎么做吗?

【问题讨论】:

  • 请添加上述 JSON。
  • @JackBashford 我添加了 JSON 数组
  • 到目前为止您尝试过什么?请发布您解决手头问题的最佳尝试,以便人们实际上可以帮助您改进您的解决方案
  • 我尝试了一些方法,但我意识到我不知道该怎么做。这就是我寻找解决方案的原因

标签: javascript json recursion


【解决方案1】:

有几个 JavaScript 库可以生成带有各种视觉辅助的动态菜单。但如果你自己实现它,你会使用这些成分:

  • 应放置菜单的容器 HTML 元素。
  • 一个 JavaScript 递归函数,用于为菜单创建 DOM 元素并将它们放置在容器元素中
  • 通过样式切换子菜单可见性的单击处理程序
  • CSS 为菜单提供一些视觉线索,并提供显示或隐藏子菜单的样式

例如:

function populateMenu(container, menu) {
    if (!menu || !menu.length) return;
    const ul = document.createElement("ul");
    for (const {title, submenus} of menu) {
        const li = document.createElement("li");
        li.textContent = title;
        li.className = "leaf";       
        if (submenus) {
            populateMenu(li, submenus, true);
            li.className = "collapsed";       
            li.addEventListener("click", (e) => { 
                if (e.target !== e.currentTarget) return;
                e.target.classList.toggle("expanded");
                e.target.classList.toggle("collapsed");
            });
        }
        ul.appendChild(li);
    }
    container.appendChild(ul);
}

// Example menu definititon:
const menu = [{ title: "menu 1", submenus: [{ title: "sub menu1" }, { title: "sub menu2", submenus: [{ title: "subsub menu1", submenus: [{ title: "susubsub menu1"}]}, { title: "subsub menu2" }]}]}, { title: "menu 2" }];
// Provide the DOM element where the menu should be inserted:
populateMenu(document.getElementById("menu"), menu);
li.collapsed > ul { display: none }
ul { cursor: pointer }
li.collapsed, li.expanded, li.leaf {
    position: relative;
    list-style-type: none;
    text-indent: -2em;
}
li.expanded:before { content: '−  ' }
li.collapsed:before { content: '+  ' }
li.leaf:before { content: '○  ' }
<div id="menu"></div>

【讨论】:

    【解决方案2】:

    遍历第 n 级嵌套数组列表,并根据要求在递归函数中编写逻辑。

    我实现了这个代码来为 PrimeNG 的上下文菜单生成一个菜单列表。

    JSON 数据 -

        [
          {
            "TITLE": "parent1",
            "SUBMENU": [
              {
                "SUBMENU": [
                  {
                    "SUBMENU": [
                      {
                        "TITLE": "Child 1"
                      }
                    ]
                  },
                  {
                    "SUBMENU": [
                      {
                        "TITLE": "Child 3"
                      }
                    ]
                  },
                  {
                    "SUBMENU": [
                      {
                        "SUBMENU": [
                          {
                            "TITLE": "Child 4"
                          }
                        ]
                      },
                      {
                        "SUBMENU": [
    
                        ]
                      }
                    ],
    
                  },
                  {
                    "SUBMENU": [
                      {
                        "SUBMENU": [
    
                        ]
                      }
                    ]
                  }
                ],
    
              }
            ],
    
          },
          {
            "TITLE": "parent2",
            "SUBMENU": [
              {
                "TITLE": "Child 4"
              }
            ],
    
          }
        ]
    

    JAVASCRIPT/Typescript 代码 -

    traveRecusrivelist(object: any[]): any[] {
        if (object) {
          let newList: any[] = [];
          for (var i = 0; i < object.length; i++) {
            if (object[i].ITEMS && object[i].ITEMS.length > 0) {
                // TODO : code you logic here
               // create your own object and push in the newList array
              let returnedList = this.traveRecusrivelist(object[i].ITEMS);
              // Example : PrimeNG MenuItem creation
              // newList.push({ label: object[i].TITLE, items: returnedList, command: (event) => { } });
              newList.push(returnedList);
            }
            else {
                // TODO : code you logic here
               // example : PrimeNG menuItem 
               // newList.push({ label: object[i].TITLE, command: (event) => { } });
               // create your own object and push in the newList array
                  newList.push(object[i]);
            }
          }
          return newList;
        }
      }
    
    let list: any[] = [];
    list = this.traveRecusrivelist(object);
    console.log(list);
    

    【讨论】:

    • 我也喜欢这样递归运行
    【解决方案3】:

    例子:

      var a = {
      "menu1": {
         title: "menu1"
       },
       "menu2": {
         title: "menu2",
         submenu: {
           "menu3" : {
              title : "menu3"
            },
           "menu4": {
             title: "menu4",
             submenu: {
              "menu5": {
               title: "menu5"
             }
           }
         }
       }
      }
     }
    
    
    
     function printMenu(menu){
         if(!menu) return "";
    
         var str = "";
         for(var i in menu)
         {
             if(menu[i].submenu)
                str+= "<li>"+menu[i].title+"<ul>"+printMenu(menu[i].submenu)+"</ul></li>";
             else
                str+= "<li>"+menu[i].title+"</li>";
         }
         return str;
     };
    
    printMenu(a); // "<li>menu1</li><li>menu2<ul><li>menu3</li><li>menu4<ul><li>menu5</li></ul></li></ul></li>"
    

    【讨论】:

      【解决方案4】:

      这是一个关于如何使用递归进入 JSON 中的每个菜单和子菜单的示例:

      var myJson ='[{"title": "menu 1", "submenus": ['+
              '{"title": "sub menu1"},'+
              ' {"title": "sub menu2", "submenus": ['+
                    ' {"title": "subsub menu1", "submenus": [{"title": "susubsub menu1"}]},'+
                      ' {"title": "subsub menu2"}'+
                  ']}]},'+
      '{"title": "menu 2"}]';
      var obj = JSON.parse(myJson);
      
      function recursive(object){
        if(object){
          for(var i = 0; i < object.length; i++){
            console.log(object[i].title);
              recursive(object[i].submenus);
          }
        }
      }
      recursive(obj);

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2019-04-17
        • 1970-01-01
        • 2015-06-25
        • 1970-01-01
        • 1970-01-01
        • 2019-03-22
        • 1970-01-01
        相关资源
        最近更新 更多