我正在开发一个导航系统,我希望父级和所有子级的宽度都能达到100%,当您用子级单击一个ul时,父级会向左滑动,子级会从右滑入。以下是我目前掌握的情况:

$(function() {

  $('.list-container ul > li.has-child').each(function() {
    $(this).find('ul').prepend('<li class="back">< Back</li>');
  });

  $(document).on('click', '.list-container ul > li', function(e) {
    e.stopPropagation();
    var children = $(this).find('ul');
    if (!$(this).hasClass('back')) {
      if (children.length > 0) {
        $(this).parent().css('left','-100%');
        $(this).find('ul > li').css('display','block');
        $(this).find('ul').css('left','100%');
      }
    }
  });

  $(document).on('click','li.back', function(e) {
    e.stopPropagation();
    $(this).parent().parent().parent().css('left','0');
    $(this).parent().css('left','200%');
  });
});

html,body {
  height:100%;
  margin:0;
}
.list-container {
  overflow:hidden;
  width:100%;
}
ul {
  width:100%;
  list-style-type:none;
  padding:0;
  margin:0;
  position:absolute;
  transition: all 0.5s ease;
}

li {
  padding:10px 0 10px 15px;
  border-bottom:1px solid black;
}
  li.has-child:after {
    display:inline-block;
    content:">";
    float:right;
    margin-right:15px;
  }
li > ul {
  display:block;
  left:200%;
  top:0;
}
li > ul > li {
  display:none;
}

<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="list-container">
  <ul>
    <li class="has-child">Test 1
      <ul>
        <li class="has-child">Test 1 sub-menu
          <ul>
            <li>Test 1 sub-sub-menu</li>
          </ul>
        </li>
        <li>Test 1 sub-menu a</li>
      </ul>
    </li>
    <li class="has-child">Test 2
      <ul>
        <li>Test 2 sub-menu</li>
        <li class="has-child">Test 2 sub-menu a
          <ul>
            <li>Test 2 sub-sub-menu</li>
          </ul>
        </li>
      </ul>
    </li>
    <li class="has-child">Test 3
      <ul>
        <li>Test 3 sub-menu</li>
        <li class="has-child">Test 3 sub-menu a
          <ul>
            <li>Test 3 sub-sub-menu</li>
          </ul>
        </li>
      </ul>
    </li>
  </ul>
</div>

这段代码按第一级/第二级项目的预期工作,但一旦您尝试单击到第三级(即“测试1子菜单”),它就会变得一团糟。我现在意识到使用uls可能比使用li更好,但是有人能建议如何在不修改HTML结构的情况下使其工作吗?如果有更好的方法来实现此功能,请打开以完全更改jQuery/CSS。

最佳答案

此代码适用于一级/二级项目,
但一旦你尝试点击进入第三级(即“测试1
子菜单“)搞砸了。
这是因为,您将ul移动一个常量200%,而子ul移动一个常量+/-100%。同时,将主ul重置为0。除此之外,当使用显示块显示菜单时,不会隐藏这些内容。虽然这适用于第一个级别,但它从第二个级别开始分离。
我现在意识到使用div可能会更好
这不是uls
是的,使用divs可能会更好,因为相对于层次uls,处理那些会更容易。但是,对于层次结构,ul会更具语义。
如果您不想更改HTML结构,那么最简单、最好的方法是指定每个子菜单都在中。这可以通过在每个有更多子项的level上添加data-属性来完成,您可以去掉li类。一旦在.has-child属性中定义了级别,就可以使用这些属性按相应的因子移动每个级别。
下面是一个粗略的演示。请注意,尽管您已经将其标记为data-,但我还是用普通的vanila JavaScript创建了这个演示,因为这对我来说更简单、更快。如果愿意的话,可以将其转换为jQuery,否则应该可以正常工作,不会有任何问题。
演示小提琴:https://jsfiddle.net/abhitalks/euLzo2dg/
演示片段:

// keep things outside the global scope
(function (window, document) {
  var attachTo = document.getElementsByClassName('list-container')[0];
  prepareNav(attachTo); // attach nav to the div

  function prepareNav(nav) {
    // prepare nav by creating back links, setting styles, and click handler
    var
      navBar = nav.firstElementChild,
      navElems = nav.querySelectorAll('li[data-level] > ul')
    ;
    for (i=0; i < navElems.length; i++) {
      var backLink = document.createElement('li');
      backLink.className = 'back';
      backLink.textContent = '\u3008' + ' Back';
      navElems[i].insertBefore(backLink, navElems[i].firstElementChild);
    }
    navBar.style.left = '0%';
    nav.addEventListener('click', function(e) {
      startNav(e, navBar, navElems);
    }, false);
  }

  function startNav(e, navBar, navElems) {
    // click handler
    if (e.target.dataset && e.target.dataset.level) {
      // move main ul by negative multiples of level
      navBar.style.left = -(e.target.dataset.level * 100) + '%';
      // reset all menus by hiding those
      [].forEach.call(navElems, function(ne) { ne.classList.remove('show'); });
      // show the parent menu
      e.target.parentNode.classList.add('show');
      // show the current menu
      e.target.firstElementChild.classList.add('show');
    }
    if (e.target.className === 'back') {
      // move back the main ul by 100 (not to 100)
      var leftPos = parseInt(navBar.style.left);
      navBar.style.left = (leftPos + 100) + '%';
    }
  }

})(window, document);

* { box-sizing: border-box; margin: 0; padding: 0; font-family: sans-serif; }
html, body { height:100%; }
.list-container {
  overflow: hidden; position: relative;
  width: 100%; min-height: 128px;
}
.list-container ul {
  width: 100%; background-color: #eee;
  list-style-type: none;
  position: absolute; left: 0%; top: 0%;
  transition: all .5s ease;
}
.list-container li {
  padding: 10px 0 10px 15px;
  cursor: pointer; border: 1px solid #aaa;
}
.list-container li:first-child { border-bottom: none; }
.list-container li:last-child { border-top: none; }
.list-container li.back + li:last-child { border-top: 1px solid #aaa;  }
.list-container li[data-level]::after {
  display: inline-block; content: '\003009';
  float: right; margin-right: 15px;
}
.list-container li[data-level]:hover,
.list-container li.back:hover { background-color: #ddd; }
.list-container li[data-level] > ul { left: 100%; top: 0; display: none; }
.list-container li[data-level] > ul.show { display: block; }

<div class="list-container">
  <ul>
    <li data-level="1">Test 1
      <ul>
        <li data-level="2">Test 1 sub-menu
          <ul>
            <li>Test 1 sub-sub-menu</li>
          </ul>
        </li>
        <li>Test 1 sub-menu a</li>
      </ul>
    </li>
    <li data-level="1">Test 2
      <ul>
        <li>Test 2 sub-menu</li>
        <li data-level="2">Test 2 sub-menu a
          <ul>
            <li>Test 2 sub-sub-menu</li>
          </ul>
        </li>
      </ul>
    </li>
    <li data-level="1">Test 3
      <ul>
        <li>Test 3 sub-menu</li>
        <li data-level="2">Test 3 sub-menu a
          <ul>
            <li>Test 3 sub-sub-menu</li>
          </ul>
        </li>
      </ul>
    </li>
  </ul>
</div>

10-06 15:57