如何创建多层手风琴菜单?

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了如何创建多层手风琴菜单?相关的知识,希望对你有一定的参考价值。

我正在尝试使用纯javascript创建多层或嵌套的手风琴菜单。整个功能正常运行,只需要解决一个问题:当我单击菜单的一个元素时,整个功能都会做出反应。

这不适用于当前项目。在完成基础课程之后,我只是想扩展我的知识。

我知道解决此问题的简便方法是将函数复制三遍,然后专门针对数组中的每个节点(即使是正确的单词?)。但是,我认为那是做事的错误方式。如您所见,我试图为多个变量创建一个循环。我认为这可能是我的问题,因为这似乎是将所有这些联系在一起的东西。

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的元素的类。因此,现在我可以通过添加或删除此类来隐藏和显示元素。

在手风琴函数中,我在单击元素之后切换该类的元素,并删除所有其他元素的类。

在手风琴子菜单中,我只是在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>

以上是关于如何创建多层手风琴菜单?的主要内容,如果未能解决你的问题,请参考以下文章

Django动态渲染多层菜单

Python之多层菜单(第1天)

递归遍历多层次菜单

Python题目2:多层菜单,进入和退出(字典)

6种方式创建多层索引MultiIndex

实现多层抽屉菜单,点击其中一项会动画打开该抽屉--第三方开源--MultiCardMenu