【问题标题】:Javascript For HTML MenuHTML菜单的Javascript
【发布时间】:2020-11-21 10:33:22
【问题描述】:

我有内部对象的多维数组及其导航菜单。我已经将该对象转换为 HTML 并且工作正常,但它是如此静态且下拉级别有限,在当前代码中我只做 2 级深度。

var nav = [{ name: 'Home', route: 'home' },{ name: 'Portfolio', route: 'portfolio' },
{ name: 'Drop Down', sub: [{ name: 'Drop Down 1' },{ name: 'Drop Down 2', sub: [{ name: 'Deep Drop Down 1' }] }] }, { name: 'Last'}]

var items = []
nav.map((val,id)=>{
    var item
        if(typeof val.sub!=='undefined'){
            var item1 = []
            var item_1
            val.sub.map((val,id)=>{
                if(typeof val.sub!=='undefined'){
                    var item2 = []
                    val.sub.map((val,id)=>{
                        item2.push('<li><a href="#">'+val.name+'</a></li>')
                    })
                    item_1 = '<li class="drop-down"><a href="#">'+val.name+'</a><ul>'+item2+'</ul></li>'
                }else{
                    item_1 = '<li><a href="#">'+val.name+'</a></li>'
                }
            item1.push(item_1)
            })
            item = '<li class="drop-down"><a href="#"></a><ul>'+item1+'</ul></li>'
        }else{
            item = '<li><a href="#">'+val.name+'</a></li>'
        }
    items.push(item)
})

console.log(items)

好吧,如果我有 5 级或更多级的下拉菜单怎么办?

[{ name: 'Home' },
        { name: 'Portfolio' },
        { name: 'Drop Down', sub: [
            { name: 'Drop Down 1' },
            { name: 'Drop Down 2', sub: [
                { name: 'Deep Drop Down 2' }, 
                { name: 'Deep Drop Down 3', sub: [
                    { name: 'Deep Deep Drop Down 1' },
                    { name: 'Deep Deep Drop Down 2', sub: [
                        { name: 'Deep Deep Deep Drop Down 1' }] 
                    }] 
                }] 
            }
        ]}, 
        { name: 'Last'}]

这将是一项艰巨的任务,并变成丑陋的代码行。这个问题有什么解决办法吗?如果可能的话,递归解决方案会更好,因为我认为它更有效。谢谢。

【问题讨论】:

  • 对此的 UX 解决方案是接受功能已超出普通菜单应完成的功能,而是例如将所有选项显示为整页模式。如果产品负责人需要额外的功能,您应该始终回到第一步,确定当前的设计解决方案是否仍然适用于该任务,或者您是否需要实施不同的解决方案。
  • 我之前有一个小项目,客户对下拉菜单的需求,但只有2级,这不是一项艰巨的任务。这个问题只是我的好奇心,我很高兴通过下面的回答帮助我解决了这个问题。
  • 是的,这是一个很好的方法。我最近创建了一个包含 webview 的本机应用程序。主页有隐藏在应用程序中的自己的菜单,因此我在 javascript 中为发送到应用程序的主页创建了一个菜单结构。所以每次我们更新首页的菜单,app都会自动更新。使用起来太容易了。 :)

标签: javascript html multidimensional-array


【解决方案1】:

递归函数调用呢?就像这样,嵌套子菜单的次数并不重要。这是一个工作示例:

const buildMenu = nav => {
    const items = [];
    nav.map((val, id) => {
        items.push(`<li><a href="#">${val.name}</a></li>`);
        if (val.sub) {
            // recursive function call
            const submenu = buildMenu(val.sub);
            items.push(submenu);
        }
    });
    // wrap with ul
    return ['<ul>', ...items, '</ul>']
}

console.log(buildMenu(nav));

返回

['<ul>',
    '<li><a href="#">Home</a></li>',
    '<li><a href="#">Portfolio</a></li>',
    '<li><a href="#">Drop Down</a></li>',
    [
        '<ul>',
        '<li><a href="#">Drop Down 1</a></li>',
        '<li><a href="#">Drop Down 2</a></li>',
        [
            '<ul>',
            '<li><a href="#">Deep Drop Down 2</a></li>',
            '<li><a href="#">Deep Drop Down 3</a></li>',
            [
                '<ul>',
                '<li><a href="#">Deep Deep Drop Down 1</a></li>',
                '<li><a href="#">Deep Deep Drop Down 2</a></li>',
                // [] and so on...
                '</ul>'
            ],
            '</ul>'
        ],
        '</ul>'
    ],
    '<li><a href="#">Last</a></li>',
'</ul>']

【讨论】:

  • 我对你的代码做了一些调整,它可以工作,谢谢
【解决方案2】:

是的,这可以通过递归函数轻松完成

const datas = [{ name: 'Home' },
{ name: 'Portfolio' },
{
  name: 'Drop Down', sub: [
    { name: 'Drop Down 1' },
    {
      name: 'Drop Down 2', sub: [
        { name: 'Deep Drop Down 2' },
        {
          name: 'Deep Drop Down 3', sub: [
            { name: 'Deep Deep Drop Down 1' },
            {
              name: 'Deep Deep Drop Down 2', sub: [
                { name: 'Deep Deep Deep Drop Down 1' }]
            }]
        }]
    }
  ]
},
{ name: 'Last' }]

-- HTML--

<body>
  <ul id="test"></ul>
</body>

-- JS--

function r(data, target) {
  data.forEach(el => {
    target.insertAdjacentHTML("beforeend", "<li>" + el.name + "</li>");
    if (el.sub) {
      const ul = document.createElement("ul");
      r(el.sub, ul)
      target.lastElementChild.insertAdjacentElement("beforeend", ul);
    }
  })
}


let test = document.getElementById('test')
r(datas, test)

好吧,让你为“ul”而苦苦挣扎,我感觉很难过。

这是一个工作版本。

【讨论】:

    【解决方案3】:

    纯 Javascript,不使其成为通用函数。

    我对导航数组进行了一些更改。

    var nav = [
      { name: 'Home', route: 'home' },
      { name: 'Portfolio', route: 'portfolio' },
      { name: 'Drop Down', route: '/drop', sub: [
        { name: 'Drop Down 1', route: '/1' },
        { name: 'Drop Down 2' , route: '/2' , sub: [
          { name: 'Deep Drop Down 1' , route: '/1' }
        ]
        }] 
      },
      { name: 'Last'}];
    
    const menu = document.querySelector('ul');
    for(var r of nav) {
      var BaseLi = document.createElement('Li');
      var routeTag = document.createElement('a');
      routeTag.href = "/"+r.route;
      routeTag.innerText = r.name;
      BaseLi.appendChild(routeTag);
      if(r.sub) {
        var subMenu = document.createElement('ul');
        for(var s of r.sub){
          var SubLi = document.createElement('Li');
          var routeTag = document.createElement('a');
          routeTag.href = "/"+r.route +"/"+s.route;
          routeTag.innerText = s.name;
          SubLi.appendChild(routeTag)
          subMenu.appendChild(SubLi);
        }
        BaseLi.appendChild(subMenu);
        if(s.sub) {
           var subMenu2 = document.createElement('ul');
          for(var s2 of s.sub){
            var SubLi2 = document.createElement('Li');
            var routeTag = document.createElement('a');
            routeTag.href = "/"+r.route +"/"+s.route+"/"+s2.route;
            routeTag.innerText = s2.name;
            SubLi2.appendChild(routeTag)
            subMenu2.appendChild(SubLi2);
          } 
          SubLi.appendChild(subMenu2);
        }
      }
      menu.appendChild(BaseLi);  
    }
    &lt;ul&gt;&lt;/ul&gt;

    【讨论】:

      猜你喜欢
      • 2012-04-02
      • 1970-01-01
      • 1970-01-01
      • 2016-12-11
      • 2013-03-03
      • 2017-12-28
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多