javascript - Vanilla js中的侧边栏多级动画下拉菜单

标签 javascript css animation

赏金

我在谷歌上搜索它以找到类似的库,但我没有找到......如果有人知道你可以给出答案(仅限 Vanilla js 库和麻省理工学院许可证)......

否则不要更改 html 结构...修复我的代码对我来说会更好..否则你可以用自己的方式解决..

结束赏金

const dataKeys = document.querySelectorAll('nav ul')
dataKeys.forEach(function(el,key){
    el.setAttribute('data-key',key);
})


const lists = document.querySelectorAll('ul ul')
lists.forEach(function(el){
    let sh = el.scrollHeight;
    el.setAttribute('data-sh',sh);
    el.classList.add('sub-menu')
    el.style.maxHeight =  0 + "px"; 
})
document.querySelectorAll("ul li").forEach(el => el.addEventListener('click', function(e){
    e.preventDefault();
    e.stopPropagation();
    try {
      let el = e.target.parentElement.children[1]; 
      let ul = e.target.parentElement.closest('ul');
      if(ul){
        ul.querySelectorAll('ul').forEach(function(item){
          item.style.minHeight = 0 + 'px';
        })
      }
      if(parseInt(getComputedStyle(el).minHeight) > 0){
        el.style.minHeight = 0 + "px";
      }else{
        el.style.minHeight =  el.scrollHeight + "px";
      }
    } catch (error) {
      return false;
    }
     return false;
}));



  document.querySelectorAll("ul ul li").forEach(el => el.addEventListener('click', function(e){

    e.preventDefault();
    e.stopPropagation();

    // const lists = document.querySelectorAll('ul ul')
    // lists.forEach(function(el){
      
    //     el.style.minHeight =  0 + "px"; 
    // })

    let el = null;
    let sh = 0;

     if(e.target.parentElement.hasChildNodes()){
      let ul = e.target.parentElement.querySelector('ul');
      if(e.target.parentElement.contains(ul)){
        el = e.target.parentElement.children[1];
        console.log(e.target.parentElement);
        console.log(e.target.parentElement.children[1]);
        sh  = el.scrollHeight;
      }
    }
      
    
      let elKey = parseInt(el.getAttribute('data-key'));

      let elli = e.target.parentElement.parentElement;

      let elH =  parseInt(el.getAttribute('data-sh'));
      let elliH =  parseInt(elli.getAttribute('data-sh'));

      // elli.style.minHeight = 0 + 'px';
      
      let elFirstChild = 0;
      if(el.hasChildNodes()){
        elFirstChild = el.children[0].scrollHeight;
        elFirstChild = parseInt(elFirstChild);
      }
    
      elli.style.minHeight = elliH + elFirstChild - elH + 'px';
      el.style.minHeight = elH + 'px';

     return false;
  }));
a {
    display: inline-block;
    width: 100%;
    height: 100%;
    padding: 5px 10px;

    color: white;
}

nav ul,
nav ul ul {
    list-style: none;
    margin: 0;
    padding: 0;
    display: flex;
    flex-direction: column;
    overflow: hidden;
}

nav ul {
    width: 200px;
    background: dodgerblue;
    position: relative;
}


nav ul ul {

    background: rgb(13, 130, 141);
    margin-left: 15px;
    border-left: 1px dashed white;
    transition: min-height .5s ease-in-out;

}

nav ul ul ul {
    background: rgb(1, 8, 8);
    margin-left: 15px;
    border-left: 1px dashed white;

}

nav ul ul ul ul {
    background: rgb(10, 41, 179);
    margin-left: 15px;
    border-left: 1px dashed white;
}
  <nav>
        <ul>
            <li><a href="javascript:void(0)">Home</a></li>
            <li><a href="javascript:void(0)">Dropdown 1 </a>
                <ul class="label-one">
                    <li><a href="javascript:void(0)"> Menu 1</a></li>
                    <li><a href="javascript:void(0)">Menu 2</a>
                        <ul class="label-two">
                            <li><a href="javascript:void(0)"> 1 Sub Menu 1</a></li>
                            <li><a href="javascript:void(0)"> 1 Sub Menu 2</a></li>
                            <li><a href="javascript:void(0)"> 1 Sub Menu 3</a> </li>
                        </ul>
                    </li>
                    <li><a href="javascript:void(0)">Menu 3</a>
                        <ul class="label-two">
                            <li><a href="javascript:void(0)"> 1 Sub Menu 1</a></li>
                            <li><a href="javascript:void(0)"> 1 Sub Menu 2</a></li>
                            <li><a href="javascript:void(0)"> 1 Sub Menu 3</a> </li>
                            <li><a href="javascript:void(0)"> 1 Sub Menu 3</a> </li>
                            <li><a href="javascript:void(0)"> 1 Sub Menu 3</a> </li>
                            <li><a href="javascript:void(0)"> 1 Sub Menu 3</a> </li>
                            <li><a href="javascript:void(0)"> 1 Sub Menu 3</a> </li>
                        </ul>
                    </li>
                    <li><a href="javascript:void(0)">Menu 4</a>
                        <ul class="label-two">
                            <li><a href="javascript:void(0)"> 1 Sub Menu 1</a></li>
                            <li><a href="javascript:void(0)"> 1 Sub Menu 2</a></li>
                            <!-- <li><a href="javascript:void(0)"> 1 Sub Menu 3</a> </li> -->
                        </ul>
                    </li>
                </ul>
            </li>
            <li><a href="javascript:void(0)">Dropdown 2 </a>
                <ul class="label-one" >
                    <li><a href="javascript:void(0)">Menu 2 </a>
                        <ul >
                            <li><a href="javascript:void(0)"> 2 Sub Menu 1</a></li>
                            <li><a href="javascript:void(0)"> 2 Sub Menu 2</a></li>
                        </ul>
                    </li>
                </ul>
            </li>
        </ul>
    </nav>

最佳答案

这是我到目前为止能做的,如果它对你有用,我可以用更整洁的方式来做(我会尝试)

我在这里创建了一个类 drop 的 div,我们可以在其中添加 <a>标签

enter image description here

function onLoad() {

  var drop = document.getElementsByClassName('drop');
  var adj_flag = 0;
  var Height = 0;
  var array = [];
  var c = [];
  var a = document.getElementsByTagName('a');
  var d;


  for (var i = 0; i < a.length; i++) {
    if (a[i].nextElementSibling != "DIV") {
      a[i].onclick = function() {
        var p = this.parentElement.children;
        for (var j = 0; j < p.length; j++) {
          if (p[j].nodeName == "DIV") {
            var decre = style_length(p[j].style.height);

            if (decre > 0) {
              p[j].style.height = "0px";
              var div = p[j];
              while (div.parentElement.nodeName == "DIV") {

                div = div.parentElement;

                div.style.height = (style_length(div.style.height) - decre) + "px";

              }
              var query_div = p[j].querySelectorAll("*");
              for (var k = 0; k < query_div.length; k++) {
                if (query_div[k].nodeName == "DIV") {
                  if (style_length(query_div[k].style.height) > 0) {
                    query_div[k].style.height = "0px";
                  }
                }
              }

            }
          }
        }
      }
    }
  }

  for (var i = 0; i < drop.length; i++) {

    drop[i].style.height = '0px';
  }

  for (var i = 0; i < drop.length; i++) {



    drop[i].previousElementSibling.onclick = function() {
      if (this.nextElementSibling.nodeName == "DIV") {
        var elem = this.nextElementSibling;

        var height_div = 0;
        if (elem.style.height == "0px") {
          var check = elem.parentElement.children;

          for (var i = 0; i < check.length; i++) {
            if (check[i].nodeName == "DIV" && check[i] != elem) {
              if (check[i].style.height != "0px") {

                c.push(check[i].previousElementSibling);


              }
            }
          }


          var height_calc = elem.children;
          for (var i = 0; i < height_calc.length; i++) {
            if (height_calc[i].nodeName == "A") {
              height_div += 38;
            }
          }


          elem.style.height = height_div + 'px';
          var flag = 0;
          var add_h = height_div;
          var changes;
          var q;
          if (c.length > 0) {

            for (var i = 0; i < c.length; i++) {
              if (style_length(c[i].nextElementSibling.style.height) != 0) {
                if (style_length(elem.style.height) == style_length(c[i].nextElementSibling.style.height)) {
                  changes = 0;
                } else {
                  if (style_length(elem.style.height) < style_length(c[i].nextElementSibling.style.height)) {
                    add_h -= style_length(c[i].nextElementSibling.style.height);
                  } else {
                    add_h -= style_length(c[i].nextElementSibling.style.height);
                  }

                }
              }
              c[i].nextElementSibling.style.height = "0px";
              q = c[i].nextElementSibling.querySelectorAll("*");
              for (var k = 0; k < q.length; k++) {
                if (q[k].nodeName == "DIV") {
                  q[k].style.height = "0px";
                }
              }
            }
          }

          while (elem.parentElement.nodeName == "DIV") {
            elem = elem.parentElement;
            var h = elem.offsetHeight + add_h;
            elem.style.height = h + 'px';

          }

          c.pop();

          flag = 0;
        } else {
          var query = elem.querySelectorAll('*');


          var sub_h = elem.clientHeight;
          elem.style.height = "0px";
          while (elem.parentElement.nodeName == "DIV") {
            elem = elem.parentElement;
            var h = elem.clientHeight - sub_h;
            elem.style.height = h + 'px';
          }

          for (var i = 0; i < query.length; i++) {
            if (query[i].nodeName == "DIV") {


              query[i].style.height = "0px";
            }
          }


        }
      }
    }
  }

  function style_length(A) {
    A = A.substring(0, A.length - 2);
    var s = parseInt(A);
    return s;
  }

}
* {
  margin: 0px;
  padding: 0px;
  color: white;
  font-family: 'arial';
}

.menu {
  position: absolute;
  margin-left: 100px;
  display: flex;
  flex-direction: column;
  width: 250px;
  min-height: 114px;
  overflow: hidden;
  background-color: black;
}

.menu a {
  background-color: black;
  text-decoration: none;
  color: white;
  padding: 10px;
}

.drop {
  background-color: black;
  transition: height 0.4s;
  display: flex;
  flex-direction: column;
  margin-left: 15px;
  height: 0px;
}
<body onload="onLoad()">
  <nav class="menu">
    <a href="#/">HOME</a>
    <a href="#/">DropDown-1</a>
    <div class="drop">
      <a href="#/" style="background-color: #00175A;">MENU-1</a>

      <a href="#/" style="background-color: #00175A;">MENU-2</a>
      <div class="drop">
        <a href="#/" style="background-color: #030E2E;">SUBMENU-1</a>
        <a href="#/" style="background-color: #030E2E;">SUBMENU-2</a>
        <div class="drop">
          <a href="#/" style="background-color:grey;">submenu-1</a>
          <a href="#/" style="background-color:grey;">submenu-2</a>
          <a href="#/" style="background-color:grey;">submenu-3</a>
        </div>
        <a href="#/" style="background-color: #030E2E;">SUBMENU-3</a>
        <div class="drop">
          <a href="#/" style="background-color:grey;">submenu-1</a>
          <a href="#/" style="background-color:grey;">submenu-2</a>
        </div>

      </div>
      <a href="#/" style="background-color: #00175A;">MENU-3</a>
      <div class="drop">
        <a href="#/" style="background-color: #030E2E;">SUBMENU-1</a>
        <a href="#/" style="background-color: #030E2E;">SUBMENU-2</a>
      </div>

    </div>
    <a href="#/">DropDown-2</a>
    <div class="drop">
      <a href="#/" style="background-color: #00175A;">MENU-2</a>
      <div class="drop">
        <a href="#/" style="background-color: #030E2E;">SUBMENU-1</a>
        <a href="#/" style="background-color: #030E2E;">SUBMENU-2</a>
      </div>

    </div>

  </nav>
</body>

关于javascript - Vanilla js中的侧边栏多级动画下拉菜单,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/65502214/

相关文章:

ios - 一起动画 UIView 的框架和圆角半径

javascript - JQuery/JavaScript - 将父行跨度增加 1 并在单击时将第一个子单元格放在下面

javascript - 捕获、记录和运行 Javascript 事件分析

Javascript:addEventListener 没有考虑更新的 DOM?

html - 如何创建嵌套的CSS水平菜单?

html - 如何在不更改文本颜色的情况下更改光标颜色?

css - 为什么容器内的 div 与页脚重叠?

c++ - 无法在 openGL 和 GLUT 中为我想要的确切对象制作动画

javascript - fancybox onStart onComplete 状态不工作

javascript - d3转换会改变哪些属性?