是否可以通过Javascript访问%-width元素的当前缩放因子而不会导致重排? [英] Is it possible to access the current scaling factor of a %-width element by Javascript without causing reflow?

查看:142
本文介绍了是否可以通过Javascript访问%-width元素的当前缩放因子而不会导致重排?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试在缓慢的UI中修复一些性能缓慢的javascript,并且我将主要原因缩小为jQuery .width()使用的调用在响应式布局中查看 width:100%元素的实际像素大小,在需要经常响应用户操作的过程中。

I'm trying to fix some slow-performing javascript in a sluggish UI, and I've narrowed the main cause down to a jQuery .width() call used to see the actual pixel size of a width: 100% element in a responsive layout, in a process that needs to happen often in response to user actions.

我添加了基于时间戳的测量结果,他们发现它仅占滞后时间的33%左右,这使得用户界面感觉锐利和UI感觉迟钝。删除这一行,UI感觉很快 - 但是,它把事情放错了地方......

I've added timestamp-based measurements and they show that it alone accounts for around 33% of the lag time, which makes the difference between the UI feeling sharp and the UI feeling sluggish. Removing this one line, the UI feels fast - but, it puts things in the wrong place...

似乎已确定 .width()在jQuery> 1.8 中相对较慢,主要有两个原因:

It seems well established that .width() is relatively slow in jQuery > 1.8 largely for two reasons:


[当您检索必须计算的度量时发生回流,例如访问offsetWidth,clientHeight或任何计算的CSS值(通过DOM兼容浏览器中的getComputedStyle()或IE中的currentStyle)

[ reflow happens when ] you retrieve a measurement that must be calculated, such as accessing offsetWidth, clientHeight, or any computed CSS value (via getComputedStyle() in DOM-compliant browsers or currentStyle in IE)

...实际上,对于像IE和Firefox这样的浏览器,为了避免相互矛盾的变化(例如在同一个函数调用中隐藏和显示),将DOM更改延迟到最后一刻,人们有时添加不必要的州吸气剂,以便强制重排

...in fact, for browsers like IE and Firefox that delay DOM changes until the last moment in order to avoid contradictory changes (e.g. hide and show in the same function call), people sometimes add unnecessary state getters in order to force reflow to occur.

还需要检查元素的边框状态。 来自他们的博客

It also needs to check the border-box state of the element. From their blog:


jQuery 1.8现在需要在使用.width()时检查box-sizing属性,以便它可以决定是否需要减去填充和边框宽度。这可能是昂贵的 - 在Chrome上高达100倍!

jQuery 1.8 now needs to check the box-sizing property whenever you use .width() so that it can decide whether it needs to subtract out the padding and border width. That can be expensive—up to 100 times more expensive on Chrome!


我的代码 width()调用的目的是查看响应式设计是否以及缩小了多少。它需要查看一个小部件的包装元素,它具有 width:100%; (但可能在列或其他容器中,具体取决于它所在的站点/页面) ,并且需要查看它实际显示的包装器最大宽度的百分比。

The purpose of my code's width() call is to see if, and by how much, a responsive design has been scaled down. It needs to look at a widget's wrapper element, which has width: 100%; (but might be in a column or other container, depending on what site/page hosts it), and needs to see what % of that wrapper's maximum width it is actually showing at.

基于不同坐标系统的其他代码为我提供了标签的位置(以像素为单位),然后我需要使用缩放系数(基本上<$ c) $ c> = $ wrapper.width()/ maxWidth; )缩小位置,例如,如果在狭窄的窗口/设备中查看页面,并且包装器是50%的它的最大尺寸,标签的顶部和左侧偏移是其默认值的50%。

Other code based on a different co-ordinate system gives me the location, in pixels, for a label, then I need to use a scaling factor (essentially = $wrapper.width() / maxWidth;) to scale down the location so that, for example, if the page is viewed in a narrow window/device and the wrapper is 50% of its maximum size, the labels' top and left offsets are 50% of their defaults.

有没有什么方法可以访问这些数据,说明%-width元素在不引起重排的情况下缩小了多少以及其他使 .width()来电慢?

Is there any way I can access this data about how much a %-width element has been scaled down without causing reflow and the other things that make .width() calls slow?

我尝试或排除过的事情:

Things I've tried or ruled out:


  • .outerWidth() .width()一样慢

  • .get(0).clientWidth (纯Javascript /非Jquery选项)也几乎和<$一样慢c $ c> .width()(据推测,因此它是重生的罪魁祸首)

  • 我注意到在大多数浏览器上,如果我做任何一个这些在其他维度中跟随上述任何一个(例如 .get(0).clientWidth 后跟 .outerHeight())在第一次非常之后调用(大约快20倍)。大概是因为刚刚完成了重排并且刚刚访问了元素属性,所以它们以某种方式被缓存。但是效果不适用于重复调用函数,仅在一个函数调用中。

  • .css(width)显然没用,因为它只给我 100% 在所有情况下

  • 我考虑过获取窗口的宽度,但事情变得复杂,具体取决于页面的列布局托管这个元素。例如,如果我的包装器采用双列布局,并且窗口比折叠两列的断点稍宽,则窗口将比包装元素的最大大小宽,但包装元素不会在100%的最大宽度。

  • .outerWidth() is exactly as slow as .width()
  • .get(0).clientWidth (the pure Javascript / non-Jquery option) is also almost exactly as slow as .width() (presumably, it's therefore the reflow that is the culprit)
  • I noticed that on most browsers, if I do any of these followed by any of the above in the other dimension (e.g. .get(0).clientWidth followed by .outerHeight()) calls after the first are very fast (~20 times faster). Presumably since the reflow has just been done and the element properties have just been accessed, they're cached somehow. But the effect doesn't hold for repeated calls to the function, only within one function call.
  • .css("width") is obviously no use because it'd just give me 100% in all cases
  • I considered getting the width of the window, but things get complicated depending on the column layouts of the page that is hosting this element. For example, if my wrapper is in a two-column layout and the window is a little wider than the breakpoint that collapses the two columns, the window will be wider than the wrapper element's max size, but the wrapper element won't be at 100% of its maximum width.

[ 更新 ]我想到我想出了一种绕过我解决问题的方法的方法,并且在不访问元素缩放的情况下定位我的标签:因为我已经拥有了 maxWidth 以像素为单位的变量和以像素为单位的偏移量,我有足够的数据来计算我的标签的百分比偏移量 leftOffset_px / maxWidth_px topOffset_px / maxHeight_px ,然后 +'%'并应用 作为每个标签的CSS 顶部偏移量。这是荒谬更快 - 现在不到1毫秒,所以我的基于时间戳的功能很快就无法测量它!

[ Update ] I thought I'd figured out a way bypass my need to solve the problem, and position my labels without accessing the scaling of the element: since I already had the maxWidth variable in pixels and the offsets in pixels, I had enough data to calculate a percentage offset for my labels with leftOffset_px / maxWidth_px and topOffset_px / maxHeight_px, then + '%' and apply that as each label's CSS top and left offset. This is ridiculously faster - now less than 1 milisecond, so fast my timestamp-based function can't measure it!

不幸的是,我也是有另一个功能,检查具有固定宽度的标签不会溢出响应容器,为此,我需要考虑容器的当前像素宽度或它的比例因子。

Unfortunately, I also have another function that checks that the labels, which have a fixed width, don't overflow the responsive container, and for that, I do need to take into account either the current pixel width of the container or its scale factor.

推荐答案

不确定改进有多大,但你可以尝试添加一个绝对定位的元素,不包含子项,只包含小部件的根目录,其唯一目的是读取其宽度。我认为绝对定位的元素只能重温它的孩子:

Not sure on how big an improvement that would be, but you could try adding an absolutely positioned element, containing no children, to the root of your widget, with the sole purpose of reading its width. I think absolutely positioned elements only reflow its children:

.root {
  position: relative;
}
.ruler {
  position: absolute;
  width: 100%;
}

_

<div class="root>
  ...
  <div class="ruler"></div>
</div>

-

var updatedWidth = $('.ruler').width()

(虽然我同意评论说你应该尝试用CSS解决这个问题

(Although I agree with comments saying you should try and resolve with CSS)

这篇关于是否可以通过Javascript访问%-width元素的当前缩放因子而不会导致重排?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆