zoukankan      html  css  js  c++  java
  • 浏览器渲染及相关性能

    一、浏览器渲染

    1、网页的生成过程

    1.解析HTML/XHML/SVG生成DOM树

    2.解析css生成CSSOM (css规则树)

    3.结合DOM和CSSOM,生成一棵渲染树(Render Tree)(包含每个节点的视觉信息)。

      Rendering Tree 渲染树并不等同于DOM树,因为一些像Header或display:none的东西就没必要放在渲染树中了。

      CSS 的 Rule Tree主要是为了完成匹配并把CSS Rule附加上Rendering Tree上的每个Element。

      CSS匹配HTML元素是一个相当复杂和有性能问题的事情。所以,你就会在N多地方看到很多人都告诉你,DOM树要小,CSS尽量用id和class,千万不要过渡层叠下去,……

    4.生成布局(layout),计算元素大小、节点位置。即将所有渲染树的所有节点进行平面合成。

    5.最后通过调用操作系统Native GUI的API绘制。

    2.重排(reflow)和 重绘(repaint)

    • Repaint——屏幕的一部分要重画,比如某个CSS的背景色变了。但是元素的几何尺寸没有变。
    • Reflow——意味着元件的几何尺寸变了,我们需要重新验证并计算Render Tree。是Render Tree的一部分或全部发生了变化。这就是Reflow,或是Layout。(HTML使用的是flow based layout,也就是流式布局,所以,如果某元件的几何尺寸发生了变化,需要重新布局,也就叫reflow )reflow 会从<html>这个root frame开始递归往下,依次计算所有的结点几何尺寸和位置,在reflow过程中,可能会增加一些frame,比如一个文本字符串必需被包装起来。

    三、对于性能的影响

    当你增加、删除、修改DOM结点时,会导致Reflow或Repaint

    • 当你移动DOM的位置,或是搞个动画的时候。
    • 当你修改CSS样式的时候。
    • 当你Resize窗口的时候(移动端没有这个问题),或是滚动的时候。
    • 当你修改网页的默认字体时。
    • 注:display:none会触发reflow,而visibility:hidden只会触发repaint,因为没有发现位置变化。

      多说两句关于滚屏的事,通常来说,如果在滚屏的时候,我们的页面上的所有的像素都会跟着滚动,那么性能上没什么问题,因为我们的显卡对于这种把全屏像素往上往下移的算法是很快。但是如果你有一个fixed的背景图,或是有些Element不跟着滚动,有些Elment是动画,那么这个滚动的动作对于浏览器来说会是相当相当痛苦的一个过程。你可以看到很多这样的网页在滚动的时候性能有多差。因为滚屏也有可能会造成reflow。

      基本上来说,reflow有如下的几个原因:

      • Initial。网页初始化的时候。
      • Incremental。一些Javascript在操作DOM Tree时。
      • Resize。其些元件的尺寸变了。
      • StyleChange。如果CSS的属性发生变化了。
      • Dirty。几个Incremental的reflow发生在同一个frame的子树上。

    四、提高性能的九个技巧

    第一条,DOM 的多个读操作(或多个写操作),应该放在一起。不要两个读操作之间,加入一个写操作。

    一般来说,浏览器会把这样的操作积攒一批,然后做一次reflow,这又叫异步reflow或增量异步reflow 。但是有些情况浏览器是不会这么做的,比如:resize窗口,改变了页面默认的字体,等。对于这些操作,浏览器会马上进行reflow。

    但是有些时候,我们的脚本会阻止浏览器这么干,比如:如果我们请求下面的一些DOM值:

    1. offsetTop, offsetLeft, offsetWidth, offsetHeight
    2. scrollTop/Left/Width/Height
    3. clientTop/Left/Width/Height
    4. IE中的 getComputedStyle(), 或 currentStyle

    因为,如果我们的程序需要这些值,那么浏览器需要返回最新的值,而这样一样会flush出去一些样式的改变,从而造成频繁的reflow/repaint。

    第二条,如果某个样式是通过重排得到的,那么最好缓存结果。避免下一次用到的时候,浏览器又要重排。

    第三条,不要一条条地改变样式,而要通过改变class,或者csstext属性,一次性地改变样式。

    第四条,尽量使用离线DOM,而不是真实的网面DOM,来改变元素样式。比如,操作Document Fragment对象,完成后再把这个对象加入DOM。再比如,使用 cloneNode() 方法,在克隆的节点上进行操作,然后再用克隆的节点替换原始节点。

    第五条,先将元素设为display: none(需要1次重排和重绘),然后对这个节点进行100次操作,最后再恢复显示(需要1次重排和重绘)。这样一来,你就用两次重新渲染,取代了可能高达100次的重新渲染。

    第六条,position属性为absolutefixed的元素,重排的开销会比较小,因为不用考虑它对其他元素的影响。

    第七条,只在必要的时候,才将元素的display属性为可见,因为不可见的元素不影响重排和重绘。另外,visibility : hidden的元素只对重绘有影响,不影响重排。

    第八条,使用虚拟DOM的脚本库,比如React等。

    第九条,使用 window.requestAnimationFrame()、window.requestIdleCallback() 这两个方法调节重新渲染

  • 相关阅读:
    NOIP 模拟 $26; m 降雷皇$
    NOIP 模拟 $26; m 神炎皇$
    NOIP 模拟 $25; m queen$
    NOIP 模拟 $25; m string$
    创建自己的数字货币
    Etherscan
    ETH挖矿
    Claymore's Dua Miner挖矿教程
    微擎微赞密码重置
    SQL引擎及事务支持
  • 原文地址:https://www.cnblogs.com/xinup/p/4876180.html
Copyright © 2011-2022 走看看