首页 Web前端,潜神默记

浏览器的渲染过程

首先,先来了解一下浏览器的渲染过程是什么样的,也就是说浏览器把一堆代码呈现到页面上的过程是什么样子的,浏览器采用的是流式布局模型(Flow Bsaed Layout),如图1所示,可以总结出浏览器的渲染步骤为:
浏览器的渲染过程

  1. 处理 HTML 并构建 DOM 树(DOM Tree)。
  2. 处理 CSS 构建 CSSOM 树(CSS Tree)。
  3. 将 DOM 与 CSSOM 合并成一个渲染树(Render Tree)。
  4. 根据渲染树来布局,计算每个节点的位置。
  5. 调用 GPU 绘制,合成图层,显示在屏幕上。

注意:

  • 在构建 CSSOM 树时,会阻塞渲染,直至 CSSOM 树构建完成。并且构建 CSSOM 树是一个十分消耗性能的过程,所以应该尽量保证层级扁平,减少过度层叠,越是具体的 CSS 选择器,执行速度越慢。
  • 当 HTML 解析到 script 标签时,会暂停构建 DOM, 完成后才会从暂停的地方重新开始。也就是说,如果你想首屏渲染的越快,就越不应该在首屏就加载 JS 文件。并且 CSS 也会影响 JS 的执行,只有当解析完样式表才会执行 JS,所以也可以认为这种情况下,CSS 也会暂停构建 DOM。

Load 和 DOMContentLoaded 区别

  • Load 事件触发代表页面中的 DOM,CSS,JS,图片已经全部加载完毕。
  • DOMContentLoaded 事件触发代表初始的 HTML 被完全加载和解析,不需要等待 CSS,JS,图片加载。
  • 图层

    一般来说,可以把普通文档流看成一个图层。特定的属性可以生成一个新的图层。不同的图层渲染互不影响,所以对于某些频繁需要渲染的建议单独生成一个新图层,提高性能。但也不能生成过多的图层,会引起反作用。
    通过以下几个常用属性可以生成新图层:

    • 3D 变换:translate3dtranslateZ
    • will-change
    • videoiframe 标签
    • 通过动画实现的 opacity 动画转换
    • position: fixed

    重绘(Repaint)和回流(Reflow)

    概念

    • 当节点需要更改外观而不会影响布局的,比如改变 colorbackground-colorvisibility等就称为重绘
    • 回流是 布局发生改变或者几何属性发生改变 就称为回流

      注意:回流一定会引起重绘,重绘不一定会引起回流

    常见引起回流的属性和方法

    任何会改变元素几何信息(元素的位置和尺寸大小)的操作,都会触发回流,

    • 页面首次渲染
    • 浏览器窗口大小发生改变
    • 元素尺寸或位置发生改变
    • 元素内容变化(文字数量或图片大小等等)
    • 元素字体大小变化
    • 添加或者删除可见DOM元素
    • 激活CSS伪类(例如::hover
    • 查询某些属性或调用某些方法

    常见引起重绘的属性和方法

    引起重绘的属性和方法

    减少重绘和回流

    • 使用 translate 替代 top
    • 使用 visibility 替换 display: none ,因为前者只会引起重绘,后者会引发回流(改变了布局)
    • DOM 离线后修改,比如:先把 DOMdisplay:none (有一次 Reflow),然后你修改 100 次,然后再把它显示出来
    • 不要把 DOM 结点的属性值放在一个循环里当成循环里的变量
    • 不要使用 table布局,可能很小的一个小改动会造成整个 table 的重新布局
    • 动画实现的速度的选择,动画速度越快,回流次数越多,也可以选择使用 requestAnimationFrame
    • CSS 选择符从右往左匹配查找,避免 DOM 深度过深
    • 将频繁运行的动画变为图层,图层能够阻止该节点回流影响别的元素。比如对于 video 标签,浏览器会自动将该节点变为图层。

    CSS

    • 避免使用 table布局
    • 尽可能在 DOM 树的最末端改变 class
    • 避免设置多层内联样式。
    • 将动画效果应用到 position 属性为 absolutefixed 的元素上。
    • 避免使用 CSS 表达式(例如:calc())。

    JavaScript

    • 避免频繁操作样式,最好一次性重写 style 属性,或者将样式列表定义为 class 并一次性更改 class 属性。
    • 避免频繁操作DOM,创建一个 documentFragment ,在它上面应用所有 DOM操作 ,最后再把它添加到文档中。
    • 也可以先为元素设置 display: none ,操作结束后再把它显示出来。因为在 display 属性为 none 的元素上进行的DOM 操作不会引发回流和重绘。
    • 避免频繁读取会引发回流/重绘的属性,如果确实需要多次使用,就用一个变量缓存起来。
    • 对具有复杂动画的元素使用绝对定位,使它脱离文档流,否则会引起父元素及后续元素频繁回流。



    文章评论

    目录