重绘和回流以及浏览器的渲染过程

81 阅读2分钟

blog.51cto.com/u_15659138/…

浏览器的渲染过程

  1. 把 html 文档解析成一棵 DOM 树
  2. 把 css 文档解析成一棵 css 规则树
  3. DOM 树和 CSS 规则树组成一棵 render 渲染树,然后就根据这个渲染树开始绘制页面

绘制过程会有两种情况,一种是重绘,一种是回流

重绘是和外观有关系,一般是 color,background-color 回流是和布局、尺寸、显示隐藏相关的 一般和带有 px 相关的

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

频繁的重绘和回流 尤其是回流会导致页面变慢,所以要尽量减少页面重绘和回流

优化的思路

  1. 浏览器本身自己的优化 UI 渲染是异步的,它会把所有要绘制放在一个队列中,等到了一定的时间间隔才会一次性批处理绘制

image.png

  1. 我们可以做的优化:我们要减少重绘和回流就是要减少对渲染树的操作,则我们可以合并多次的 DOM 和样式的修改
  2. 尽量不要使用一堆的行内样式操作,而是把要操作的全部写在类 clas 中,然后直接调用这个类名
  3. 在操作之前先把这块 display:none;然后把所有的操作全部做完,然后再 display:block,这样只会有两次重绘和回流
  4. 使用克隆元素的技术,实现复用
  5. 在写动画的时候可以用脱离文档流,避免对文档其他地方有影响

image.png 8. 使用 DocumentFragment 文档碎片(不要直接在 DOM 树上操作,而是先搞一个文档碎片,在这个文档碎片上把所有的操作全部做完,在这个文档碎片上做的任何操作不会触发重绘和回流,因为和 DOM 树没有关系,等操作全部搞定,再把这个文档碎片追加到 DOM 树上,只会导致一次重绘和回流)

image.png

<script>
// 没有使用文档碎片之前的写法,会导致101次重绘和回流
  var ul = document.createElement('ul')
  document.body.append(ul)
  for(var i=0;i<100;i++){
    var li = document.createElement('li')
    li.innerHTML = i;
    ul.append(li)
  }
</script>
<script>
// 只有一次重绘和回流
      var documentFragment = document.createDocumentFragment();
      var ul = document.createElement("ul");
      documentFragment.append(ul);
      for (var i = 0; i < 100; i++) {
        var li = document.createElement("li");
        li.innerHTML = i;
        ul.append(li);
      }
      document.body.append(documentFragment);
    </script>