优化 JS/jQuery 性能 (getBoundingClientRect) 并消除布局重绘
所以我有一个项目,我试图最大限度地优化一个相当复杂的 Javascript 函数 - 部分原因是它应该在智能手机(Webkit)上运行并且每一点都很重要。
我一直在使用各种调试和计时技术来检查我的代码并重写所有可能很慢的内容 - 例如基于 jQuery 的部分,其中本机可能会做得更好等等。该函数的作用基本上是获取一串 html 文本,并将其剪切为恰好适合 3 个没有固定位置或大小的 DIV(客户端模板机制)。
目前,整个函数在 iPad 浏览器中执行大约需要 100 毫秒(但在生产环境中,理想情况下我需要执行 200 次),问题是,在这 100 毫秒中,至少有 20 毫秒是因为这一行代码(在 3 个循环中):
var maxTop = $(cur).offset().top + $(cur).outerHeight();
“cur”只是对容器 DIV 元素的引用,上面的行正在计算其底部位置(因此我的文本应该在哪里中断)。通过查看 offset jQuery 代码,我了解到它使用 getBoundingClientRect ,甚至消除 jQuery 偏移/大小调整并直接调用它并不能加快速度 - 所以它的 getBoundingClientRect 错误(至少在 Webkit 中)。我对此做了一些研究,我知道它会导致布局重绘。
但仍然无法相信我执行了多个 DOM 清除/克隆/追加,并且所有这些都比简单的元素位置查找快得多?有什么想法吗?也许是 webkit 特定的东西?或者不会导致重绘的东西?
非常感谢!
So I have a project where I'm trying to optimize a fairly complex Javascript function to the max - partly this is due to the fact that its supposed to run on smart-phones (Webkit) and every little bit counts.
I've been using various debugging and timing techniques to go through my code and rewrite everything that might be slow - like parts of jQuery based stuff where native might do better and so on. What the function does is basically take a string of html text and cut it up to fit exactly into 3 DIVs that do not have fixed position or size (a client templating mechanism).
At the moment the entire function takes around 100ms to execute in iPads browser (but in the production environment I need to ideally execute it 200 times) and the problem is that out of those 100ms at least 20ms are because of this single line of code (in 3 loops):
var maxTop = $(cur).offset().top + $(cur).outerHeight();
"cur" is just a reference to a container DIV element and the line above is calculating its bottom position (so where my text should break). From looking at the offset jQuery code I understand it uses getBoundingClientRect and even eliminating jQuery offset/sizing and calling it directly does nothing to speed it up - so its getBoundingClientRect fault (at least in Webkit). I did a bit of research on it and I understand it causes layout redraw.
But still - can't believe that I do multiple DOM clears/clones/appends and all of those are much faster than a simple element position lookup? Any ideas out there? Maybe something webkit specific? Or something that doesn't cause redraw?
Would much appreciate it!
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
由于我也遇到了类似的问题,因此我有一个循环,其中修复了一系列(有时超过 1000 个)DOM 元素(从浮点到绝对)。我立即将固定样式应用于元素,这是一个很大的错误:每次向 DOM 写入内容时,当脚本要求元素的位置时,都必须重新计算样式。因此,先进行所有阅读,然后再进行所有编写,即使这意味着两个单独的循环(您可以安全地写入 DOM 元素的 dataset 属性)。
另请参阅:http://gent. ilcore.com/2011/03/how-not-to-trigger-layout-in-webkit.html
Since I also ran into a similar problem, I had a loop in which I was fixing a series (sometimes 1000+) of DOM elements (from float to absolute). I immediately applied the fixed styling to the elements, which was a big mistake to make: Every time something is written to the DOM the style has to be recalculated when your script asks for a position of an element. Hence, do all your reading, and then all your writing, even if that means two separate loops (you can safely write to the dataset property of your DOM element).
See also: http://gent.ilcore.com/2011/03/how-not-to-trigger-layout-in-webkit.html
你尝试过吗:
?
重点是,offsetTop 和 offsetHeight 是原生 dom 属性,因此访问应该比通过函数更快。
did you try:
?
point is, offsetTop and offsetHeight are native dom properties, and so access should be faster than through a function.