我有几百个“行”元素,如下所示:
<div class='row'>
<div class='cell'></div>
<div class='cell'></div>
<div class='cell'></div>
</div>
我们需要在已经在页面上呈现之后获取clientHeight . 我知道“clientHeight”属性强制重排,这会影响我的表现,因为它们有很多 . 但是 - 它们已经被渲染,我知道它们的大小在渲染时间和查询高度的时间之间没有变化 .
在查询高度时,是否有办法告诉浏览器不要重排?此外 - webkit检查员说:
Layout tree size 5901
Layout scope Whole document
div是一个绝对定位的祖先 - 不应该只是绝对定位的元素被回流?
Edit:
所以提供的答案是正确的 . 我实际上弄脏了布局,因为我有这个循环:
rows.each(function(){
$(this).css('height', this.clientHeight);
});
将代码更改为此修复了问题:
var heights = rows.map(function(){
return this.clientHeight;
});
rows.each(function(){
$(this).css('height', heights.shift());
});
3 回答
clientHeight属性不强制重排,至少不是自己 . 你需要两件事来触发回流:
脏了当前布局(设置宽度或高度等布局属性)
查询布局属性(例如clientHeight)
您可以轻松批量调用以设置宽度或高度,并且在JS上下文放弃控制之前不会发生重排 . 您可以轻松地批量查询布局属性,如果当前布局不脏,则不会发生重排 .
连续执行1和2时会出现问题 . 强制重排是为了满足您的查询准确信息 .
据我所知,你是正确的,有一个绝对定位的祖先应该限制回流在整个文件“蔓延”(绝对定位的祖先的父母将不会回流) . 绝对定位的祖先里面的所有物品仍然会回流!
至于你的问题的解决方案是的 . 设置一个缓存机制,像这样(伪代码):
然后,您可以根据需要多次使用
div.getClientHeight()
而不是div.clientHeight
,只有第一次使用才会触发重排(如果是脏的) .显然,与第一个建议保持一致,您也可以在一个批次(=一个回流)中人工查询clientHeight中的所有div,之后您就不再有问题了 .
只要DOM发生变化,Reflow就会排队,但只有在以下情况之一时执行:
没有更多的javascript要处理(脚本结束)或
查询必须呈现的计算值时,如
clientHeight
.因此,为了避免回流,您必须遵循以下规则
在更改DOM时不要查询DOM
如果要查询它,请不要更改DOM
实际上,这意味着在完成修改DOM之后,应该在脚本末尾对所有查询操作进行分组 . 这样做只会为数千个元素重排一次,而不是每个元素重复数千次 .
这是一个古老的问题,但我在研究这个问题时偶然发现了它,所以我想我会分享我在研究其他人时发现的东西 .
有一个非常好的库可以帮助您避免强制回流,尤其是在较大的应用程序上:https://github.com/wilsonpage/fastdom .
该库的想法是将读取和写入分组到不同的阶段 .