我正在尝试使用纯 JavaScript 创建多层或嵌套 Accordion 菜单。整个功能正常运行,但有一个问题:当我单击菜单的一个元素时,整个功能都会使用react。
这不适用于当前元素。我只是想在参加基础类(class)后扩展我的知识。
我知道解决此问题的简单但臃肿的方法是将函数复制三次,然后专门针对数组中的每个节点(这个词是否正确?)。但是,我认为那是错误的做事方式。正如您将看到的,我试图为多个变量创建一个循环。我认为这可能是我的问题,因为它似乎是将所有这些联系在一起的东西。
var accordion = document.getElementsByClassName("accordion");
var dropdown = document.getElementsByClassName("dropdown");
var accordionArrow = document.getElementsByClassName("accordionArrow");
var dropdownArrow = document.getElementsByClassName("dropdownArrow");
var content = document.getElementsByClassName("content");
function accordionFunction() {
for (j = 0, k = 0, l = 0, m = 0; j < dropdown.length, k < accordionArrow.length, l < dropdownArrow.length, m < content.length; j++, k++, l++, m++) {
if (dropdown[j].style.maxHeight) {
dropdown[j].style.maxHeight = null;
accordionArrow[k].style.transform = null;
content[m].style.maxHeight = null;
dropdownArrow[l].style.transform = null;
} else {
dropdown[j].style.maxHeight = dropdown[j].scrollHeight + "px";
accordionArrow[k].style.transform = "rotate(-135deg)";
}
}
};
for (var i = 0; i < accordion.length; i++) {
accordion[i].addEventListener("click", accordionFunction);
};
function accordionSubmenu() {
for (l = 0, m = 0; l < dropdown.length, m < content.length; l++, m++) {
if (content[m].style.maxHeight) {
content[m].style.maxHeight = null;
dropdownArrow[l].style.transform = null;
} else {
content[m].style.maxHeight = content[m].scrollHeight + "px";
dropdownArrow[l].style.transform = "rotate(-135deg)";
}
}
};
for (j = 0; j < dropdown.length; j++) {
dropdown[j].addEventListener("click", accordionSubmenu)
};
body {
margin: auto;
width: 600px;
}
div {
margin: auto;
}
.accordion {
background-color: lightblue;
color: white;
padding: 3%;
cursor: pointer;
width: 300px;
height: 50px;
}
.accordion .accordionArrow {
border: solid white;
border-width: 0 3px 3px 0;
display: inline-block;
padding: 3px;
transform: rotate(45deg);
}
.dropdown {
color: lightblue;
padding-left: 3%;
cursor: pointer;
width: 300px;
max-height: 0;
overflow: hidden;
transition-duration: 0.2s;
}
.dropdown .dropdownArrow {
border: solid lightblue;
border-width: 0 3px 3px 0;
display: inline-block;
padding: 3px;
transform: rotate(45deg);
}
.content {
font-weight: bold;
transition: all 0.2s ease;
padding-left: 5%;
max-height: 0;
overflow: hidden;
}
<div>
<h2 class="accordion">Main 1<i class="accordionArrow"></i></h2>
<h3 class="dropdown">Submenu 1<i class="dropdownArrow"></i></h3>
<p class="content">Hello there. We are exposed.</p>
</div>
<div>
<h2 class="accordion">Main 2<i class="accordionArrow"></i></h2>
<h3 class="dropdown">Submenu 1<i class="dropdownArrow"></i></h3>
<p class="content">Hello there. We are exposed again!</p>
</div>
<div>
<h2 class="accordion">Main 3<i class="accordionArrow"></i></h2>
<h3 class="dropdown">Submenu 1<i class="dropdownArrow"></i></h3>
<p class="content">Hello there. We are exposed thrice!</p>
</div>
最佳答案
通过巧妙地使用 this
关键字(触发事件处理程序的元素)和 nextElementSibling
属性,您可以以更优雅的方式实现这一点。
我创建了一个类来使元素的最大高度为 0。所以现在我可以通过添加或删除此类来隐藏和显示元素。
在 Accordion 函数中,我为单击元素之后的元素切换此类,并删除所有其他元素的类。
在 Accordion 子菜单中,我只是在 nextElementSibling
上切换类。
我个人会制作一个不同的 html 结构,您可以通过使用更多级别的元素来更轻松地切换类,因此您只需要 1 个函数来处理 x 个子菜单。也许对您来说是一个不错的新挑战。
document.querySelectorAll('.accordion').forEach((accordion) => accordion.addEventListener('click', function() {
//Get All possible hidden elements and loop over it.
document.querySelectorAll('.dropdown, .content').forEach((collapsible) => {
//If current element is the same is the next sibling element of the event target toggle the class. Otherwise add it.
if(collapsible === this.nextElementSibling) {
collapsible.classList.toggle('maxHeightZero');
}
else {
collapsible.classList.add('maxHeightZero');
}
});
}));
document.querySelectorAll('.dropdown').forEach((dropdown) => dropdown.addEventListener('click', function() {
//toggle the nextElementSibling
this.nextElementSibling.classList.toggle('maxHeightZero');
}));
body {
margin: auto;
width: 600px;
}
div {
margin: auto;
}
.accordion {
background-color: lightblue;
color: white;
padding: 3%;
cursor: pointer;
width: 300px;
height: 50px;
}
.accordion .accordionArrow {
border: solid white;
border-width: 0 3px 3px 0;
display: inline-block;
padding: 3px;
transform: rotate(45deg);
}
.dropdown {
color: lightblue;
padding-left: 3%;
cursor: pointer;
width: 300px;
overflow: hidden;
transition-duration: 0.2s;
}
.dropdown .dropdownArrow {
border: solid lightblue;
border-width: 0 3px 3px 0;
display: inline-block;
padding: 3px;
transform: rotate(45deg);
}
.content {
font-weight: bold;
transition: all 0.2s ease;
padding-left: 5%;
overflow: hidden;
}
.maxHeightZero {
max-height: 0;
}
<div>
<h2 class="accordion">Main 1<i class="accordionArrow"></i></h2>
<h3 class="dropdown maxHeightZero">Submenu 1<i class="dropdownArrow"></i></h3>
<p class="content maxHeightZero">Hello there. We are exposed.</p>
</div>
<div>
<h2 class="accordion">Main 2<i class="accordionArrow"></i></h2>
<h3 class="dropdown maxHeightZero">Submenu 1<i class="dropdownArrow"></i></h3>
<p class="content maxHeightZero">Hello there. We are exposed again!</p>
</div>
<div>
<h2 class="accordion">Main 3<i class="accordionArrow"></i></h2>
<h3 class="dropdown maxHeightZero">Submenu 1<i class="dropdownArrow"></i></h3>
<p class="content maxHeightZero">Hello there. We are exposed thrice!</p>
</div>
关于javascript - 如何创建多层 Accordion 菜单?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58305715/