草庐IT

减少回流与重绘

不见水星记 2023-03-28 原文

一、前情回顾

  • 在讨论回流与重绘之前,我们要知道:

    • 浏览器使用流式布局模型 (Flow Based Layout)。
    • 浏览器会把HTML解析成DOM,把CSS解析成CSSOM,DOM和CSSOM合并就产生了Render Tree。
    • 有了RenderTree,我们就知道了所有节点的样式,然后计算他们在页面上的大小和位置,最后把节点绘制到页面上。
    • 由于浏览器使用流式布局,对Render Tree的计算通常只需要遍历一次就可以完成,但table及其内部元素除外,他们可能需要多次计算,通常要花3倍于同等元素的时间,这也是为什么要避免使用table布局的原因之一。

二、回流/重排

  • 概念:当渲染树中部分或者全部元素的尺寸、结构或者属性发生变化时,浏览器会重新渲染部分或者全部文档的过程就称为回流/重排。
  • 触发条件:
    • 页面的首次渲染
    • 浏览器的窗口大小发生变化
    • 元素的内容发生变化
    • 元素的尺寸或者位置发生变化
    • 元素的字体大小发生变化
    • 激活CSS伪类
    • 查询某些属性或者调用某些方法
    • 添加或者删除可见的DOM元素

三、重绘

  • 概念:当页面中某些元素的样式发生变化,但是不会影响其在文档流中的位置时,浏览器就会对元素进行重新绘制,这个过程就是重绘。
  • 触发条件:
    • color、background 相关属性:background-color、background-image 等
    • outline 相关属性:outline-color、outline-width 、text-decoration
    • border-radius、visibility、box-shadow

四、如何避免回流与重绘

  • 浏览器针对页面的回流与重绘,进行了自身的优化——渲染队列
    • 浏览器会将所有的回流、重绘的操作放在一个队列中,当队列中的操作到了一定的数量或者到了一定的时间间隔,浏览器就会对队列进行批量处理。这样就会让多次的回流、重绘变成一次回流重绘。
  • CSS
    • 避免设置多层内联样式。
    • 如果需要设置动画效果,最好使用absolute或者fixed,使元素脱离文档流,这样他们发生变化就不会影响其他元素。
    • 避免使用CSS表达式(例如:calc())。
  • JS
    • 避免频繁操作样式,最好将样式列表定义为class并一次性更改class属性。避免频繁操作样式,最好将样式列表定义为class并一次性更改class属性。
    • 避免频繁操作DOM,创建一个documentFragment,在它上面应用所有DOM操作,最后再把它添加到文档中。
    • 可以先为元素设置为不可见:display: none,操作结束后再把它显示出来。因为在display属性为none的元素上进行的DOM操作不会引发回流和重绘。

五、解释上述的documentFragment

  • 概念:DocumentFragment,文档片段接口,一个没有父对象的最小文档对象。它被作为一个轻量版的 Document使用,就像标准的document一样,存储由节点(nodes)组成的文档结构。与document相比,最大的区别是DocumentFragment不是真实 DOM 树的一部分,它的变化不会触发 DOM 树的重新渲染,且不会导致性能等问题。
  • 与直接操作DOM的区别:由于DocumentFragment不会出现在文档树中,将DocumentFragment插入文档树中,相当于把把他的子孙节点插入到文档树中,在频繁的DOM操作时,我们就可以将DOM元素插入DocumentFragment,之后一次性的将所有的子孙节点插入文档中。和直接操作DOM相比,将DocumentFragment 节点插入DOM树时,仅会触发页面的一次重绘,这样就大大提高了页面的性能。

六、总结

回流一定重绘,重绘不一定回流。

有关减少回流与重绘的更多相关文章

  1. ruby - 减少数组时使用 Hash.new 作为初始值 - 2

    我有一个这样的数组[1,1,2,3,3,3,4,5,5]我想计算每个数字出现的次数,我正在尝试这样做[1,1,2,3,3,3,4,5,5].reduce(Hash.new(0)){|hash,number|hash[number]+=1}问题是当我尝试运行它时出现以下错误NoMethodError:undefinedmethod`[]='for1:Fixnumfrom(irb):6:in`blockinirb_binding'from(irb):6:in`each'from(irb):6:in`reduce'from(irb):6我能像这样设置初始值吗,还是我弄错了?

  2. ruby-on-rails - 如何(大量)减少 Rails 应用程序中的 SQL 查询数量? - 2

    在我的Rails应用程序中,我有users,它可以有许多invoices,而invoices又可以有许多payments。现在在dashboardView中,我想总结一个user曾经收到的所有payments,按年、季度或月。付款也分割为毛额、Netty和税额。user.rb:classUser:items).allpayments_with_invoice.select{|x|range.cover?x.date}.sum(&:"#{kind}_amount")endend发票.rb:classInvoicepayment.rb:classPaymentdashboards_cont

  3. ruby - 减少挂起 Sinatra 应用程序 - 2

    我正在尝试将Bootstrap添加到Sinatra应用程序中。我已经设置了编译路径bootstrap.less和responsive.less.在Web浏览器中分别加载两个样式表会按预期工作。但是当我尝试在html页面中使用它们时,我的应用程序挂起。我只能用kill-9停止应用程序.似乎Lessimports和multiplestylesheets以某种方式导致应用程序挂起。我能够隔离问题:app.rbrequire'rubygems'require'bundler/setup'require'sinatra'require'less'get'/'dohaml:indexendget'

  4. ruby - 在 Ruby 1.8.7 中显示时间减少到毫秒 - 2

    我试图让我的应用程序显示时间精确到毫秒(例如11:37:53.231),但是1.8.7中的strftime似乎没有选项(http://ruby-doc.org/core-1.8.7/Time.html#method-i-strftime)。在Ruby>=1.9.3中,有%3N选项(http://ruby-doc.org/core-1.9.3/Time.html#method-i-strftime),但它不在1.8.7的文档中,而且似乎也不起作用。这是我在Ruby1.8.7中得到的输出。cur_time=Time.now#=>MonJun2412:43:14+09002013cur_ti

  5. ruby - 减少 Heroku 编译的 Slug 大小 - 2

    我刚刚在bamboo-ree-1.8.7堆栈下将我的应用程序上的Rails更新到v2.3.6,编译后的slug大小已经增长到40.5Mb!在最后一次gitpush之前,slug大小约为20Mb,并且使用的是railsv2.3.5。是不是因为我的slug安装了两个rails版本?可能我遗漏了一些东西,但我没有在我的应用程序中添加任何特殊代码/文件来将slug大小增加~20Mb。你能告诉我如何减小slug的大小吗?任何帮助将不胜感激。非常感谢您。 最佳答案 一个有用的方法是将.slugignore文件添加到项目的根目录,以告诉Herok

  6. Ruby 将所有空格减少为单个空格 - 2

    我不确定该怎么做,因为我对正则表达式还很陌生,而且似乎找不到合适的方法来完成这个但是说我有以下字符串(所有制表符和换行符包括)1/2cuponion(chopped)如何删除所有空格并仅用一个空格替换每个实例? 最佳答案 在这种情况下,正则表达式可以很好地工作,因为您希望对整个类别的空白字符一视同仁,并用单个空白字符替换空白字符的任意组合。因此,如果该字符串存储在s中,那么您将执行:fixed_string=s.gsub(/\s+/,'') 关于Ruby将所有空格减少为单个空格,我们在S

  7. ruby - 减少哈希值 - 2

    我对reduce的语法有疑问。我有以下格式的散列:H={"Key1"=>1,"Key2"=>2}我想使用reduce求此函数中值的总和。类似的东西H.reduce(0){|memo,elem|memo+=elem}我知道这是错误的。我不明白如何使elem成为散列的值。 最佳答案 您可以通过将值分成2个变量来使elem包含该值:H.reduce(0){|memo,(key,val)|memo+val} 关于ruby-减少哈希值,我们在StackOverflow上找到一个类似的问题:

  8. 《安富莱嵌入式周报》第301期:ThreadX老大离开微软推出PX5 RTOS第5代系统,支持回流焊的自焊接PCB板设计,单色屏实现多级灰度播放视频效果 - 2

    往期周报汇总地址:嵌入式周报-uCOS&uCGUI&emWin&embOS&TouchGFX&ThreadX-硬汉嵌入式论坛-PoweredbyDiscuz! 祝大家开工大吉视频版:https://www.bilibili.com/video/BV1GT411o7zr1、ThreadX老大离开微软,开发的第5代RTOS系统PX5RTOS正式上线最早是看到IAR的一条消息,全面支持PX5RTOS,然后就进一步上他们的官方下载白皮书了解相关消息当看到这两个名字时,很熟悉,这不就是ThreadX的老大BillLamie。 经过信息检索,应该是实锤了,领英上已经更新了他的工作经历: 然后再结合Azur

  9. javascript - 减少用于生产的 node_modules 的大小 - 2

    我们的部署过程需要很长时间,部分原因是将node_modules文件夹传递到生产服务器。我的Package.json看起来像这样:{"name":"coms-sass","version":"0.0.1","description":"SassgulptaskforCOMSServicePortal","main":"gulpfile.js","dependencies":{"angular":"^1.5.5","angular-sanitize":"=1.5.5","angular-ui-bootstrap":"^1.3.2","gridster":"^0.5.6","gulp":"

  10. javascript - 在缩放/拖动时缩放/重绘 d3.js 网格线 - 2

    我昨天才开始使用d3.js,但在完成我的工作时遇到了一些麻烦。现在我创建了一个带有两个y轴的图表,每个显示一些值,x轴显示日期。点击y轴上的值,我会显示相应的水平网格线。我的问题是,在放大或缩小或拖动时,网格线(水平和垂直)无法根据轴值正确缩放,它们根本就不动。我今天下午进行了很多搜索,找到了一些如何执行此操作的示例,但它们似乎都不适用于我已有的代码。我想,应该将逻辑添加到缩放行为中,但我不确定//xaxisgridlinesfunctionmake_x_gridlines(){returnd3.axisBottom(x).ticks(5)}//addtheXgridlinesletx

随机推荐