ul列表js实现下拉与关闭

1.html部分        

 <body>

    <ul class="menu-container">

      <li class="menu">

        <h2>菜单1</h2>

        <ul class="subment">

          <li>菜单1</li>

          <li>菜单2</li>

          <li>菜单3</li>

          <li>菜单4</li>

        </ul>

      </li>

      <li class="menu">

        <h2>菜单2</h2>

        <ul class="subment">

          <li>菜单1</li>

          <li>菜单2</li>

          <li>菜单3</li>

          <li>菜单4</li>

        </ul>

      </li>

      <li class="menu">

        <h2>菜单3</h2>

        <ul class="subment">

          <li>菜单1</li>

          <li>菜单2</li>

          <li>菜单3</li>

          <li>菜单4</li>

        </ul>

      </li>

      <li class="menu">

        <h2>菜单4</h2>

        <ul class="subment">

          <li>菜单1</li>

          <li>菜单2</li>

          <li>菜单3</li>

          <li>菜单4</li>

        </ul>

      </li>

    </ul>

    <!-- <script src="./index.js"></script> -->

    <script src="./index2.js"></script>

    <script src="../animate.js"></script>

  </body>

2.css部分

*{

  margin: 0;

  padding: 0;

  box-sizing: border-box;

  list-style: none;

  font-weight: normal;

}

.menu-container{

  width: 200px;

  margin:0 auto;

  line-height: 30px ;

}

.menu-container h2{

  padding:0 25px;

  background: teal;

  cursor: pointer;

}

.subment{

  background:thistle;

  padding:0 30px;

  height:0;

  overflow:hidden;

}

.menu{

  margin:20px 0;

}

.subment li{

  height:30px;

}

3.js部分

var titles = document.querySelectorAll(".menu h2"); //获取所有的标题元素

var isHeight = 30; //定义每个li的高度

var totalMS = 300; //定义动画的总时间

var testSubment = document.querySelector(".subment"); //测试函数

for (let i = 0; i < titles.length; i++) {

  //通过循环给每个h2元素注册点击事件

  titles[i].onclick = function () {

    var beforeSubment = document.querySelector(".subment[status=opened]"); //获取ul中 自定义属性[status=opened]

    if (beforeSubment) {

      //beforeSubment为true时, 有自定义属性,调用关闭子标签的函数

      closeSubmenu(beforeSubment);

    }

    toggleSubmenu(this.nextElementSibling); //this.nextElementSibling 返回指定元素之后的下一个兄弟元素(相同节点树层中的下一个元素节点)

    // console.log(this.nextElementSibling);

  };

}

// console.log(titles.length * isHeight);

//打开子菜单

function openSubment(sub) {

  //自定义属性status   三种状态: 关闭:colsed,打开:opened,动画打开中:playing

  var status = sub.getAttribute("status"); //获取自定义属性

  if (status !== "closed" && status) {

    //如果当前状态 不等于关闭 和 为true 表示在打开中

    return; //什么也不做 直接返回

  }

  sub.setAttribute("status", "playing"); //更改status的状态为: 打开中 playing

  //因为涉及动画效果,调用之前封装的动画函数claerAnimate({})

  claerAnimate({

    from: 0, //开始的值

    to: sub.children.length * isHeight, //结束的值,当前子元素的长度 * 每个li的高度

    totalMS: totalMS, // 动画变化的总时间

    onmove: function (n) {

      sub.style.height = n + "px"; //要改变的回调函数,高度的变化就等对应传入参数的值 n

    },

    onend: function () {

      sub.setAttribute("status", "opened"); //终止的回调函数,重新赋值status的状态为: 打开中 opened

    },

  });

}

//关闭子菜单

function closeSubmenu(sub) {

  //自定义属性status   三种状态: 关闭:colsed,打开:opened,动画打开中:playing

  var status = sub.getAttribute("status");

  if (status !== "opened") {

    return;

  }

  sub.setAttribute("status", "playing");

  claerAnimate({

    from: sub.children.length * isHeight, //开始的值

    to: 0, //结束的值,当前子元素的长度 * 每个li的高度

    totalMS: totalMS, // 动画变化的总时间

    onmove: function (n) {

      sub.style.height = n + "px"; //要改变的回调函数,高度的变化就等对应传入参数的值 n

    },

    onend: function () {

      sub.setAttribute("status", "closed"); //终止的回调函数,重新赋值status的状态为: 打开中 opened

    },

  });

}

//切换子菜单

function toggleSubmenu(sub) {

  var status = sub.getAttribute("status"); //获取自定义属性

  //如果 status的状态为playing 运行中时   啥也不做

  if (status === "playing") {

    return;

    //如果 status的状态为opened打开时   调用closeSubmenu(sub)关闭子菜单

  } else if (status === "opened") {

    closeSubmenu(sub);

  } else {

    openSubment(sub); //如果 status的状态为closed打开时   调用openSubment(sub)打开子菜单

  }

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值