jquery - 带有后退按钮的 jquery 多级菜单 - 正在创建多个后退按钮元素
问题描述
我正在开发移动菜单交互
它应该如何工作:
单击“打开”时,会显示一个带有两个 li 项目的 ul 元素。当单击任一 li 项目时,会显示一个嵌套的 ul,如果其中的任何 li 项目有子项,则标记中还包含一个显示“更多”的跨度。
当我单击“更多”时,我看到带有 li 项目的第三级 ul,并且使用 jquery 创建了一个后退按钮并附加到第三级菜单。
问题
当我单击第一个父 li 时,我得到了预期的结果。当我单击另一个父 li 及其子项然后“返回”时,我看到正在创建多个“返回”元素。
我无法解释为什么。我的逻辑可能存在缺陷,我希望有人能帮助我发现它。或者建议一种更好地调试它的方法。
提前致谢。如果需要,我可以详细说明
小提琴:https ://jsfiddle.net/left23/ktdsxk1d/
var toggle_expand = $('.toggle-expand');
var menu = $('#main-nav');
var expand_menu = $('.expand-sub');
var sub_menu = $('.main-menu--sub');
var first_level_item = $('#main-nav > .main-menu > li');
var second_level_menu = $('#main-nav > .main-menu > li > .main-menu--sub-1');
var second_level_item = $('#main-nav > .main-menu > li > .main-menu > li');
var third_level_menu = $('.main-menu--sub-2');
// Mobile Menu Show/Hide.
toggle_expand.on('click', function(e) {
$(this).toggleClass('toggle-expand--open');
menu.toggleClass('main-nav--open');
if (!$(this).hasClass('toggle-expand--open')) {
reset();
}
});
// top level menu items
first_level_item.on('click', function(e) {
first_level_item.not(this).each(function() {
$(this).removeClass('active');
$(this).children(second_level_menu).removeClass('main-menu--sub-open');
});
$(this).toggleClass('active');
$(this).children('.main-menu--sub').toggleClass('main-menu--sub-open');
expandMenu();
});
// second level menu items
function expandMenu() {
expand_menu.on('click', function(e) {
$(this).addClass('expand-sub--open');
$(this).next(third_level_menu).addClass('main-menu--sub-open');
$(this).closest(first_level_item).addClass('active');
e.stopPropagation();
backButton();
});
}
// back button
function backButton() {
var back_button_html = '<div class="back-button">Back</div>';
// append element to bottom of list
third_level_menu.append(back_button_html);
var back_button = $('.back-button');
back_button.on('click', function(e) {
console.log('back');
$(this).parent(third_level_menu).removeClass('main-menu--sub-open');
$(this).parent(third_level_menu).prev(expand_menu).removeClass('expand-sub--open');
$(this).parents('#main-nav > .main-menu > li').addClass('active');
back_button.remove();
e.stopPropagation();
});
}
// reset to starting state
function reset() {
console.log('reset');
first_level_item.removeClass('active');
sub_menu.removeClass('main-menu--sub-open');
expand_menu.removeClass('expand-sub--open');
$('.back-button').remove();
}
解决方案
这个问题的主要原因是因为您third_level_menu
同时创建了两个按钮并绑定了两个按钮click()
事件。所以如果我们点击一个more
按钮并切换到另一个按钮并再次first_level_item
点击more
按钮,那么它会不断地创建back
按钮并将一个click
事件绑定到所有back
按钮,包括那些已经绑定了click
事件的按钮。
当我们在 之间切换时first_level_item
,会expandMenu()
遇到与我上面提到的相同的问题。
因此,在绑定click()
事件之前,我们可以off()
使用原始事件来避免多次触发相同的事件。back
另外,选择要删除的右侧按钮。
$('.back-button:visible');
和third_level_menu
附加新back
按钮的权利。
$('.main-menu--sub-2:visible');
var toggle_expand = $('.toggle-expand');
var menu = $('#main-nav');
var expand_menu = $('.expand-sub');
var sub_menu = $('.main-menu--sub');
var first_level_item = $('#main-nav > .main-menu > li');
var second_level_menu = $('#main-nav > .main-menu > li > .main-menu--sub-1');
var second_level_item = $('#main-nav > .main-menu > li > .main-menu > li');
var third_level_menu = $('.main-menu--sub-2');
// Mobile Menu Show/Hide.
toggle_expand.on('click', function(e) {
$(this).toggleClass('toggle-expand--open');
menu.toggleClass('main-nav--open');
if (!$(this).hasClass('toggle-expand--open')) {
reset();
}
});
// top level menu items
first_level_item.on('click', function(e) {
first_level_item.not(this).each(function() {
$(this).removeClass('active');
$(this).children(second_level_menu).removeClass('main-menu--sub-open');
});
$(this).toggleClass('active');
$(this).children('.main-menu--sub').toggleClass('main-menu--sub-open');
expandMenu();
});
// second level menu items
function expandMenu() {
expand_menu.off('click').on('click', function(e) {
$(this).addClass('expand-sub--open');
$(this).next(third_level_menu).addClass('main-menu--sub-open');
$(this).closest(first_level_item).addClass('active');
e.stopPropagation();
backButton();
});
}
// back button
function backButton() {
var back_button_html = '<div class="back-button">Back</div>';
// append element to bottom of list
$('.main-menu--sub-2:visible').append(back_button_html);
var back_button = $('.back-button:visible');
back_button.on('click', function(e) {
console.log('back');
$(this).parent(third_level_menu).removeClass('main-menu--sub-open');
$(this).parent(third_level_menu).prev(expand_menu).removeClass('expand-sub--open');
$(this).parents('#main-nav > .main-menu > li').addClass('active');
$(this).remove();
e.stopPropagation();
});
}
// reset to starting state
function reset() {
console.log('reset');
first_level_item.removeClass('active');
// not sure if we want this! Consider a starting state
sub_menu.removeClass('main-menu--sub-open');
expand_menu.removeClass('expand-sub--open');
$('.back-button').remove();
}
.main-nav {
display: none;
width: 90%;
}
.main-nav--open {
display: block;
}
.main-nav {
z-index: 99;
}
.main-nav>ul.main-menu {
display: flex;
flex-direction: row;
flex-wrap: nowrap;
align-items: flex-start;
padding: 0 1rem;
}
.main-nav>ul.main-menu>li.main-menu__item {
flex: 0 1 33%;
position: relative;
display: flex;
justify-content: space-around;
align-content: flex-start;
background: red;
margin-right: 1rem;
}
.main-nav>ul.main-menu>li.main-menu__item>a {
display: block;
padding: 1rem;
text-align: center;
color: white;
font-weight: 700;
text-transform: uppercase;
text-decoration: none;
transition: padding 0.2s;
}
.main-nav>ul.main-menu>li.main-menu__item.active>a {
padding: 2rem 1rem;
}
.main-nav>ul.main-menu>li.main-menu__item.active>.main-menu--sub-open {
z-index: 20;
}
.main-nav>ul.main-menu>li.main-menu__item>ul.main-menu.main-menu--sub.main-menu--sub-1 {
display: none;
position: fixed;
background: rgba(0, 0, 0, 0.6);
padding: 1rem 1rem 0;
width: 50vw;
top: 160px;
left: 0;
bottom: 0;
}
.main-nav>ul.main-menu>li.main-menu__item>ul.main-menu.main-menu--sub.main-menu--sub-1.main-menu--sub-open {
display: block;
}
.main-nav>ul.main-menu>li.main-menu__item>ul.main-menu.main-menu--sub.main-menu--sub-1>li.main-menu__item.main-menu__item--with-sub.main-menu__item--sub.main-menu__item--sub-1 {
border-top: 1px solid white;
display: flex;
justify-content: space-between;
}
.main-nav>ul.main-menu>li.main-menu__item>ul.main-menu.main-menu--sub.main-menu--sub-1>li.main-menu__item.main-menu__item--with-sub.main-menu__item--sub.main-menu__item--sub-1:first-child {
border: 0 none;
}
.main-nav>ul.main-menu>li.main-menu__item>ul.main-menu.main-menu--sub.main-menu--sub-1>li.main-menu__item.main-menu__item--with-sub.main-menu__item--sub.main-menu__item--sub-1>a {
display: block;
padding: 1rem 0;
color: white;
font-weight: 700;
text-transform: uppercase;
text-decoration: none;
}
.main-nav>ul.main-menu>li.main-menu__item>ul.main-menu.main-menu--sub.main-menu--sub-1>li.main-menu__item.main-menu__item--with-sub.main-menu__item--sub.main-menu__item--sub-1>ul.main-menu.main-menu--sub.main-menu--sub-1.main-menu--sub-2 {
display: none;
position: fixed;
background: rgba(0, 0, 0, 1);
padding: 1rem 1rem 0;
width: 50vw;
top: 160px;
left: 0;
bottom: 0;
z-index: 5;
}
.main-nav>ul.main-menu>li.main-menu__item>ul.main-menu.main-menu--sub.main-menu--sub-1>li.main-menu__item.main-menu__item--with-sub.main-menu__item--sub.main-menu__item--sub-1>ul.main-menu.main-menu--sub.main-menu--sub-1.main-menu--sub-2.main-menu--sub-open {
display: block;
}
.main-nav>ul.main-menu>li.main-menu__item>ul.main-menu.main-menu--sub.main-menu--sub-1>li.main-menu__item.main-menu__item--with-sub.main-menu__item--sub.main-menu__item--sub-1>ul.main-menu.main-menu--sub.main-menu--sub-1.main-menu--sub-2>li.main-menu__item.main-menu__item--with-sub.main-menu__item--sub.main-menu__item--sub-1.main-menu__item--sub-2 {
border-top: 1px solid white;
display: flex;
justify-content: space-between;
}
.main-nav>ul.main-menu>li.main-menu__item>ul.main-menu.main-menu--sub.main-menu--sub-1>li.main-menu__item.main-menu__item--with-sub.main-menu__item--sub.main-menu__item--sub-1>ul.main-menu.main-menu--sub.main-menu--sub-1.main-menu--sub-2>li.main-menu__item.main-menu__item--with-sub.main-menu__item--sub.main-menu__item--sub-1.main-menu__item--sub-2:first-child {
border: 0 none;
}
.main-nav>ul.main-menu>li.main-menu__item>ul.main-menu.main-menu--sub.main-menu--sub-1>li.main-menu__item.main-menu__item--with-sub.main-menu__item--sub.main-menu__item--sub-1>ul.main-menu.main-menu--sub.main-menu--sub-1.main-menu--sub-2>li.main-menu__item.main-menu__item--with-sub.main-menu__item--sub.main-menu__item--sub-1.main-menu__item--sub-2>a {
display: block;
padding: 1rem 0;
color: white;
font-weight: 700;
text-transform: uppercase;
text-decoration: none;
}
.toggle-expand {
display: inline-block;
text-align: right;
padding: 1rem;
text-decoration: none;
}
.toggle-expand--open {
background-color: white;
}
.toggle-expand__open {
display: inline-block;
text-align: center;
}
.toggle-expand--open .toggle-expand__open {
display: none;
}
.toggle-expand__close {
display: none;
text-align: center;
}
.toggle-expand--open .toggle-expand__close {
display: inline-block;
}
.back-button {
cursor: pointer;
display: inline-block;
height: 2rem;
width: auto;
color: white;
position: absolute;
right: 1rem;
padding: 1rem;
background: red;
}
.expand-sub {
cursor: pointer;
display: inline-block;
height: 2rem;
width: auto;
color: black;
position: absolute;
right: 1rem;
padding: 1rem;
background: rgba(255, 255, 255, 0.4);
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<a href="#" id="toggle-expand" class="toggle-expand toggle-expand--open">
<span class="toggle-expand__open">
Close
</span>
<span class="toggle-expand__close">Click to open menu</span>
</a>
<nav id="main-nav" class="main-nav">
<ul class="main-menu">
<li class="main-menu__item main-menu__item--with-sub">
<a class="main-menu__link main-menu__link--with-sub" href="#">
Item 1
</a>
<ul class="main-menu main-menu--sub main-menu--sub-1">
<li class="main-menu__item main-menu__item--with-sub main-menu__item--sub main-menu__item--sub-1 main-menu__item--with-sub">
<a class="main-menu__link main-menu__link--with-sub main-menu__link--sub main-menu__link--sub-1 main-menu__link--with-sub" href="#">
Item 1 Child 1</a>
<span class="expand-sub">more</span>
<ul class="main-menu main-menu--sub main-menu--sub-1 main-menu--sub main-menu--sub-2">
<li class="main-menu__item main-menu__item--with-sub main-menu__item--sub main-menu__item--sub-1 main-menu__item--with-sub main-menu__item--sub main-menu__item--sub-2">
<a class="main-menu__link main-menu__link--with-sub main-menu__link--sub main-menu__link--sub-1 main-menu__link--with-sub main-menu__link--sub main-menu__link--sub-2" href="#">Item 1 Child 1 Grandchild 1</a>
</li>
<li class="main-menu__item main-menu__item--with-sub main-menu__item--sub main-menu__item--sub-1 main-menu__item--with-sub main-menu__item--sub main-menu__item--sub-2">
<a class="main-menu__link main-menu__link--with-sub main-menu__link--sub main-menu__link--sub-1 main-menu__link--with-sub main-menu__link--sub main-menu__link--sub-2" href="#">Item 1 Child 1 Grandchild 2</a>
</li>
</ul>
</li>
</ul>
</li>
<li class="main-menu__item main-menu__item--with-sub">
<a class="main-menu__link main-menu__link--with-sub" href="#">
Item 2
</a>
<ul class="main-menu main-menu--sub main-menu--sub-1">
<li class="main-menu__item main-menu__item--with-sub main-menu__item--sub main-menu__item--sub-1 main-menu__item--with-sub">
<a class="main-menu__link main-menu__link--with-sub main-menu__link--sub main-menu__link--sub-1 main-menu__link--with-sub" href="#">
Item 2 Child 1</a>
<span class="expand-sub">more</span>
<ul class="main-menu main-menu--sub main-menu--sub-1 main-menu--sub main-menu--sub-2">
<li class="main-menu__item main-menu__item--with-sub main-menu__item--sub main-menu__item--sub-1 main-menu__item--with-sub main-menu__item--sub main-menu__item--sub-2">
<a class="main-menu__link main-menu__link--with-sub main-menu__link--sub main-menu__link--sub-1 main-menu__link--with-sub main-menu__link--sub main-menu__link--sub-2" href="#">Item 2 Child 1 Grandchild 1</a>
</li>
<li class="main-menu__item main-menu__item--with-sub main-menu__item--sub main-menu__item--sub-1 main-menu__item--with-sub main-menu__item--sub main-menu__item--sub-2">
<a class="main-menu__link main-menu__link--with-sub main-menu__link--sub main-menu__link--sub-1 main-menu__link--with-sub main-menu__link--sub main-menu__link--sub-2" href="#">Item 2 Child 1 Grandchild 2</a>
</li>
</ul>
</li>
</ul>
</li>
</ul>
</nav>
推荐阅读
- c - 如何在此 C 代码中释放所有动态分配的内存实例
- testing - Lambda 不能用 Spock 测试?
- r - 如何在超级计算机上正确运行 Caret?
- ansible - 在具有多个主机的 Ansible 剧本中从一个角色访问另一个角色的变量
- python - python api验证号码usinf firebase
- python - cv2.imwrite() 系统错误:
返回 NULL 而不设置错误 - html - CSS文件中自动完成HTML类名的VS代码扩展
- javascript - Tailwind css,如何设置默认字体颜色?
- java - Android studio“MethodHandle.invoke 和 MethodHandle.invokeExact 仅支持从 Android O (--min-api 26) 开始”构建 APK 时出错
- mongodb - 不确定如何在 MongoDB 中建模多对多关系