运行此代码:
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毫秒,值是正确的。好的,设置超时将是解决问题的一个选项,但我认为必须有一个比这更优雅的解决方案。有人知道这个解决方案吗?
答案 0 :(得分:2)
回到浏览器(setTimeout
是单向,requestAnimationFrame
是另一种方式)确实是这样做的。它允许浏览器时间呈现结果,这会在您添加元素的任务完成后的某个时间发生(在您的情况下,运行load
事件的任务处理程序)。
setTimeout
起作用;我过去不得不在Firefox上使用60到100之间的值,而是在目标环境中进行测试。您也可以使用requestAnimationFrame
回调,这种回调发生的时间早于100毫秒(假设浏览器未被阻止):
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;
该示例适用于Firefox,Chrome和Edge(&#34;适用于我&#34; =&gt;我在rAF中看到offsetTop
的0,1002,2004和3006回调)。
答案 1 :(得分:1)
您也可以使用MutationObserver,因为它会在元素添加到DOM(此处为.wrapper
)后触发。
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;