重新计算父母身高的问题

时间:2018-08-07 14:00:53

标签: javascript

我正在构建移动菜单。它分为三个级别。当您单击链接时,它将向单击的链接和下一个ul添加一个开放类。我正在通过遍历所有子级并组合每个元素的高度来计算ul的高度。这部分工作正常,我遇到的问题是在计算第二级子代时,我也需要能够重新计算父代ul,但这需要在子代ul得到计算后发生,以便获得新的高度。

测试用例:

  1. 点击父对象1

  2. 单击子级1(高度不会重新计算)

  3. 单击“父级1”关闭,再次单击(高度已重新计算)

{
  const primary = document.querySelector(".primary"),
    secondary = document.querySelectorAll(".secondary"),
    children = document.querySelectorAll(".has-children");

  for (let [i, _this] of children.entries()) {
    let currentUL = secondary[i];

    _this.addEventListener("click", e => {
      e.preventDefault();

      // toggle open class
      _this.classList.toggle("open");
      currentUL.classList.toggle("open");

      let children = currentUL.children,
        total = 0;
      for (let x = 0; x < children.length; x++) {
        total = total + children[x].offsetHeight;
      }
      currentUL.classList.contains("open") ?
        (currentUL.style.height = `${total}px`) :
        (currentUL.style.height = 0);
    });
  }
}
.primary {
  max-width: 500px;
  margin: 0 auto;
}

.primary a {
  display: block;
  padding: 20px;
  border-bottom: 1px solid grey;
  font-size: 16px;
  color: green;
}

.secondary {
  height: 0;
  overflow: hidden;
  transition-delay: 0.3s;
  transition: height 0.3s ease;
  margin-left: 38px;
}
<ul class="primary">
  <li>
    <a href="" class="has-children">Parent 1</a>
    <ul class="secondary">
      <li>
        <a href="" class="has-children">Child 1</a>
        <ul class="secondary">
          <li>
            <a href="">1</a>
          </li>
          <li>
            <a href="">2</a>
          </li>
          <li>
            <a href="">3</a>
          </li>
          <li>
            <a href="">4</a>
          </li>
          <li>
            <a href="">5</a>
          </li>
          <li>
            <a href="">6</a>
          </li>
          <li>
            <a href="">7</a>
          </li>
          <li>
            <a href="">8</a>
          </li>
          <li>
            <a href="">9</a>
          </li>
          <li>
            <a href="">10</a>
          </li>
        </ul>
      </li>
    </ul>
  </li>
</ul>

1 个答案:

答案 0 :(得分:1)

问题是,当用户单击文本“父母1”时,第一个ul.secondary元素的高度正确更新,但是当用户单击“孩子1”时,仅第二个ul.secondary高度是正确更新,但第一个ul.secondary未正确更新。可能的解决方案是,一旦子项发生更改,重新计算父项ul,由于动画延迟,我在计算父项高度之前使用了timeout 0.3秒。

要检查我在说什么,可以使用浏览器的开发工具,在“元素”选项卡上,查看在每次用户交互后如何修改元素的属性style.height

我添加的代码在评论// This is the code I added

之后

   
    const primary = document.querySelector(".primary"),
          secondary = document.querySelectorAll(".secondary"),
          children = document.querySelectorAll(".has-children");

    for (let [i, _this] of children.entries()) {
        let currentUL = secondary[i];

        _this.addEventListener("click", e => {
            e.preventDefault();

            // toggle open class
            _this.classList.toggle("open");
            currentUL.classList.toggle("open");

            calculateULHeight(currentUL);

             // This is the code I added
             let parentUL = currentUL.parentElement.parentElement;

            if (parentUL.classList.contains('secondary')) {
                setTimeout(function() {
                    calculateULHeight(parentUL);
                }, 300);
            }
        });
    }

    function calculateULHeight(UL) {
        let children = UL.children,
            total = 0;
   
        for (let x = 0; x < children.length; x++) {
            total = total + children[x].offsetHeight;
        }

        UL.classList.contains("open") ?
          (UL.style.height = `${total}px`) :
          (UL.style.height = 0);
    }
.primary {
  max-width: 500px;
  margin: 0 auto;
}

.primary a {
  display: block;
  padding: 20px;
  border-bottom: 1px solid grey;
  font-size: 16px;
  color: green;
}

.secondary {
  height: 0;
  overflow: hidden;
  transition-delay: 0.3s;
  transition: height 0.3s ease;
  margin-left: 38px;
}
<ul class="primary">
  <li>
    <a href="" class="has-children">Parent 1</a>
    <ul class="secondary">
      <li>
        <a href="" class="has-children">Child 1</a>
        <ul class="secondary">
          <li>
            <a href="">1</a>
          </li>
          <li>
            <a href="">2</a>
          </li>
          <li>
            <a href="">3</a>
          </li>
          <li>
            <a href="">4</a>
          </li>
          <li>
            <a href="">5</a>
          </li>
          <li>
            <a href="">6</a>
          </li>
          <li>
            <a href="">7</a>
          </li>
          <li>
            <a href="">8</a>
          </li>
          <li>
            <a href="">9</a>
          </li>
          <li>
            <a href="">10</a>
          </li>
        </ul>
      </li>
    </ul>
  </li>
</ul>