如何检查HTMLElement是否已满载

时间:2018-06-11 10:20:01

标签: javascript html css

运行此代码:

window.onload = function () {
  const sections = document.querySelectorAll("section");
  let eT = [];
  for (let i = 0, len = sections.length; i < len; i++) {
      const el = sections[i];
      if (el.parentNode.className !== "wrapper") {
          const wrapper = document.createElement("div");
          wrapper.className = "wrapper";
          el.parentNode.appendChild(wrapper);
          wrapper.appendChild(el);
      }
      const elCont = document.querySelectorAll(".wrapper")[i];
      eT[i] = elCont.offsetTop;
      setTimeout(() => {
          console.log(eT[i], elCont.offsetTop)
      }, 100);
  }
}
section{
  width: 100vw;
  height: 1000px;
  position: relative;
  border: 1px solid;
}
body{
  position: relative;
}
<body>
<section></section>
<section></section>
<section></section>
<section></section>
</body>

正如你所看到的那样,DOM操作,然后读取它们offsetTops发生得太快,所以如果我在创建它们之后立即读取offsetTops,将它们添加到正文中,然后将这些部分作为子项添加到它们中,则值是错误的。但是,如果我等待100毫秒,值是正确的。好的,设置超时将是解决问题的一个选项,但我认为必须有一个比这更优雅的解决方案。有人知道这个解决方案吗?

2 个答案:

答案 0 :(得分:2)

回到浏览器(setTimeout是单向,requestAnimationFrame是另一种方式)确实是这样做的。它允许浏览器时间呈现结果,这会在您添加元素的任务完成后的某个时间发生(在您的情况下,运行load事件的任务处理程序)。

在大多数情况下,超时为0的

setTimeout起作用;我过去不得不在Firefox上使用60到100之间的值,而是在目标环境中进行测试。您也可以使用requestAnimationFrame回调,这种回调发生的时间早于100毫秒(假设浏览器未被阻止):

&#13;
&#13;
window.onload = function () {
  const sections = document.querySelectorAll("section");
  let eT = [];
  for (let i = 0, len = sections.length; i < len; i++) {
      const el = sections[i];
      if (el.parentNode.className !== "wrapper") {
          const wrapper = document.createElement("div");
          wrapper.className = "wrapper";
          el.parentNode.appendChild(wrapper);
          wrapper.appendChild(el);
      }
      const elCont = document.querySelectorAll(".wrapper")[i];
      eT[i] = elCont.offsetTop;
      requestAnimationFrame(() => {
          console.log(eT[i], elCont.offsetTop)
      });
  }
}
&#13;
section{
  width: 100vw;
  height: 1000px;
  position: relative;
  border: 1px solid;
}
body{
  position: relative;
}
&#13;
<body>
<section></section>
<section></section>
<section></section>
<section></section>
</body>
&#13;
&#13;
&#13;

该示例适用于Firefox,Chrome和Edge(&#34;适用于我&#34; =&gt;我在rAF中看到offsetTop的0,1002,2004和3006回调)。

答案 1 :(得分:1)

您也可以使用MutationObserver,因为它会在元素添加到DOM(此处为.wrapper)后触发。

&#13;
&#13;
window.onload = function(){
  const sections = document.querySelectorAll("section");

  //https://developer.mozilla.org/en-US/docs/Web/API/MutationObserver
  var tObserver = new MutationObserver(function(mutations){
    if(mutations){
      for(let i=0, len=sections.length; i<len; i++){
        console.log('MutationObserver', sections[i].offsetTop)
      };

      this.disconnect()
    }
  });

  tObserver.observe(document, {attributes: false, childList: true, characterData: true, subtree: true});

  let eT = [];
  for(let i=0, len=sections.length; i<len; i++){
    const el = sections[i];
    if(el.parentNode.className !== "wrapper"){
      const wrapper = document.createElement("div");
      wrapper.className = "wrapper";
      el.parentNode.appendChild(wrapper);
      wrapper.appendChild(el);
    };

    const elCont = document.querySelectorAll(".wrapper")[i];
    eT[i] = elCont.offsetTop;
    console.log('in for loop', elCont.offsetTop);

    setTimeout(() => {
      console.log('in timeout', elCont.offsetTop)
    }, 100)
  }
}
&#13;
section{
  border: 1px solid;
  height: 1000px;
  position: relative;
  width: 100vw
}

body{
  position: relative
}
&#13;
<section></section>
<section></section>
<section></section>
<section></section>
&#13;
&#13;
&#13;