我试图在一个缓慢的UI中修复一些执行缓慢的javascript,并且我已经将主要原因缩小到一个jQuery .width()
调用,用于查看响应式布局中width: 100%
元素的实际像素大小,在响应用户操作的过程中需要经常发生。
我添加了基于时间戳的测量,它们显示仅它就占了大约33%的延迟时间,这使得UI感觉敏锐和UI感觉迟钝之间的差异。删除这一行,UI感觉很快-但是,它把东西放在错误的地方…
.width()
在jQuery> 1.8中相对较慢,这似乎是公认的,主要有两个原因:
-
在计算元素大小时强制回流。从一篇文章引用何时回流发生在DOM环境?:
[回流发生时]你检索测量必须计算,如访问offsetWidth, clientHeight,或任何计算的CSS值(通过getComputedStyle()在dom兼容的浏览器或currentStyle在IE)
…事实上,对于像IE和Firefox这样的浏览器,延迟DOM更改直到最后一刻,以避免相互矛盾的更改(例如,在同一个函数调用中隐藏和显示),人们有时会添加不必要的状态getter,以便强制回流发生。
它还需要检查元素的边框状态。来自他们的博客:
jQuery 1.8现在需要在使用。width()时检查box-sizing属性,以便它可以决定是否需要减去填充和边框宽度。这可能会很昂贵——在Chrome上要贵100倍!
我代码的width()
调用的目的是查看响应式设计是否缩小了,以及缩小了多少。它需要查看小部件的包装器元素,该元素具有width: 100%;
(但可能在列或其他容器中,取决于它所在的站点/页面),并且需要查看该包装器的最大宽度的百分比。
基于不同坐标系统的其他代码给出了标签的位置(以像素为单位),然后我需要使用缩放因子(本质上是= $wrapper.width() / maxWidth;
)来缩小位置,以便,例如,如果页面在狭窄的窗口/设备中查看,并且包装器是其最大尺寸的50%,则标签的顶部和左侧偏移量是其默认值的50%。
是否有任何方法我可以访问这些数据关于多少%-width元素已经缩小而不引起回流和其他事情,使.width()
调用缓慢?
我尝试过或排除的事情:
-
.outerWidth()
和.width()
一样慢 -
.get(0).clientWidth
(纯Javascript/非jquery选项)也几乎完全和.width()
一样慢(推测,因此回流是罪魁祸首) - 我注意到,在大多数浏览器上,如果我在另一个维度(例如
.get(0).clientWidth
后面跟着.outerHeight()
)中执行上述任何一项,那么在第一次调用之后非常快(~快20倍)。大概是因为流刚刚完成,元素属性刚刚被访问,它们以某种方式被缓存。但是,这种效果不适用于对该函数的重复调用,只适用于一次函数调用。 -
.css("width")
显然没有用因为在所有情况下它只会给我100%
- 我考虑过获得窗口的宽度,但是事情变得复杂,这取决于承载该元素的页面的列布局。例如,如果我的包装器是两列布局,窗口比折叠两列的断点稍宽,窗口将比包装器元素的最大尺寸更宽,但包装器元素不会达到其最大宽度的100%。
[Update]我认为我已经找到了一种绕过我需要解决问题的方法,并在不访问元素缩放的情况下定位我的标签:因为我已经有了以像素为单位的maxWidth
变量和以像素为单位的偏移量,我有足够的数据来计算百分比偏移量为我的leftOffset_px / maxWidth_px
和topOffset_px / maxHeight_px
标签,然后是+ '%'
,并应用作为每个标签的CSS top
和left
偏移量。这快得可笑 -现在不到1毫秒,快到我的基于时间戳的函数无法测量它!
不幸的是,我还有另一个函数来检查标签,它有一个固定的宽度,不会溢出响应容器,为此,I do需要考虑容器的当前像素宽度或其比例因子。
不确定这将是多大的改进,但您可以尝试在小部件的根目录中添加一个绝对定位的元素,不包含子元素,其唯一目的是读取其宽度。我认为绝对定位的元素只会回流它的子元素:
.root {
position: relative;
}
.ruler {
position: absolute;
width: 100%;
}
_
<div class="root>
...
<div class="ruler"></div>
</div>
var updatedWidth = $('.ruler').width()
(虽然我同意评论说你应该尝试用CSS解决)