我正在开发一个导航系统,我希望父级和所有子级的宽度都能达到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
是的,使用div
s可能会更好,因为相对于层次ul
s,处理那些会更容易。但是,对于层次结构,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>