当元素快速调整大小时,JavaScript的offsetWidth和offsetHeight给出错误的值

时间:2019-03-28 02:09:03

标签: javascript html css

我正在使用香草javascript创建自己的滚动条组件。该元素是可调整大小的,因此在调整其大小时,滚动条的最大滚动位置和大小将随之变化。

如果我以正常速度调整大小,一切都很好,但是如果我快速测试,则计算结果(大小和最大位置)会产生错误的结果,我猜是因为THE TITLEoffsetWidth错误

我的滚动条的渲染功能在调整大小时触发, sbv表示垂直滚动条,sbh表示水平滚动条

offsetHeight

有人知道为什么会这样吗? TiA

1 个答案:

答案 0 :(得分:1)

那仅仅是一个理论上的答案,因为我没有花时间来设置一个repro案例,并且因为“ 产生错误的结果”的描述有点宽泛。


我怀疑问题实际上与您的主张相反: offsetWidthoffsetHeightscrollHeightscrollWidth实际上为您提供了正确的值,这意味着您可能没想到。

这些属性,为了返回正确的值,会触发对文档中元素的所有边界框的重新计算,这称为“ reflow”
此重排意味着您以前设置的所有CSS规则现在都已应用并处于活动状态。

所以在您的代码中,当您这样做

elem.size = content.offsetHeight / content.scrollHeight;
elem.style.height = (elem.size * 100) + "%";
elem.max = (100 - elem.size * 100) / 100 * content.offsetHeight;

第一行content.offsetHeight的值与第三行的值可能不再相同。

var elem = document.getElementById('elem');
var content = document.getElementById('content');

console.log('before', content.offsetHeight);
elem.size = content.offsetHeight / content.scrollHeight;
elem.style.height = (elem.size * 100) + "%";
elem.max = (100 - elem.size * 100) / 100 * content.offsetHeight;
console.log('after', content.offsetHeight);
body{
  height: 100vh;
}
#content,#elem {
  border: 1px solid;
}
#elem {
  height: 800px;
}
<div id="content">
  <div id="elem"></div>
</div>

因此,不仅触发这样的多次重排对于性能而言是可怕的,而且您的计算可能确实会出错。

最好的办法是在传递变量之前先缓存所有当前值,进行所有计算,最后只设置所有新样式。

还请注意,所有这些效果最好在requestAnimationFrame去抖器中进行,因此每个绘画帧仅发生一次。