前端面试查漏补缺--(五) 渲染机制及重绘和回流

前言

本系列最开始是为了本身面试准备的.后来发现整理愈来愈多,差很少有十二万字符,最后决定仍是分享出来给你们.html

为了分享整理出来,花费了本身大量的时间,起码是只本身用的三倍时间.若是喜欢的话,欢迎收藏,关注我!谢谢!前端

文章连接

合集篇:

前端面试查漏补缺--Index篇(12万字符合集) 包含目前已写好的系列其余十几篇文章.后续新增值文章不会再在每篇添加连接,强烈建议议点赞,关注合集篇!!!!,谢谢!~vue

后续更新计划

后续还会继续添加设计模式,前端工程化,项目流程,部署,闭环,vue常考知识点 等内容.若是以为内容不错的话欢迎收藏,关注我!谢谢!面试

求一分内推

目前本人也在准备跳槽,但愿各位大佬和HR小姐姐能够内推一份靠谱的武汉 前端岗位!邮箱:bupabuku@foxmail.com.谢谢啦!~算法

渲染机制

渲染步骤

浏览器的渲染机制通常分为如下几个步骤:设计模式

    1. 处理 HTML 并构建 DOM 树。
    1. 处理 CSS 构建 CSSOM 树。
    1. 将 DOM 与 CSSOM 合并成一个渲染树。
    1. 根据渲染树来布局,计算每一个节点的位置。
    1. 调用 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)

概念

重绘和回流是渲染步骤中的一小节,可是这两个步骤对于性能影响很大。缓存

  • 重绘是 当节点须要更改外观而不会影响布局的,好比改变 color、background-color、visibility等就叫称为重绘
  • 回流是 布局或者几何属性须要改变 就称为回流。

注意: 回流一定会发生重绘,重绘不必定会引起回流。回流所需的成本比重绘高的多,改变深层次的节点极可能致使父节点的一系列回流。

会致使回流的操做:

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

一些经常使用且会致使回流的属性和方法:

  • clientWidthclientHeightclientTopclientLeft
  • offsetWidthoffsetHeightoffsetTopoffsetLeft
  • scrollWidthscrollHeightscrollTopscrollLeft
  • scrollIntoView()scrollIntoViewIfNeeded()
  • getComputedStyle()
  • getBoundingClientRect()
  • scrollTo()

重绘和回流与Event loop关系

不少人不知道的是,重绘和回流其实和 Event loop 有关。

  1. 当 Event loop 执行完 Microtasks 后,会判断 document 是否须要更新。由于浏览器是 60Hz 的刷新率,每 16ms 才会更新一次。
  2. 而后判断是否有 resize 或者 scroll ,有的话会去触发事件,因此 resize 和 scroll 事件也是至少 16ms 才会触发一次,而且自带节流功能。
  3. 判断是否触发了 media query
  4. 更新动画而且发送事件
  5. 判断是否有全屏操做事件
  6. 执行 requestAnimationFrame 回调
  7. 执行 IntersectionObserver 回调,该方法用于判断元素是否可见,能够用于懒加载上,可是兼容性很差
  8. 更新界面
  9. 以上就是一帧中可能会作的事情。若是在一帧中有空闲时间,就会去执行 requestIdleCallback 回调。

减小重绘和回流

  • 使用 translate 替代 top
  • 使用 visibility 替换 display: none ,由于前者只会引发重绘,后者会引起回流(改变了布局)

  • 把 DOM 离线后修改,好比:先把 DOM 给 display: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操做不会引起回流和重绘。
  • 避免频繁读取会引起回流/重绘的属性,若是确实须要屡次使用,就用一个变量缓存起来。
  • 对具备复杂动画的元素使用绝对定位,使它脱离文档流,不然会引发父元素及后续元素频繁回流。

感谢及参考

整篇文章基本都是摘自下面文章,这里表示感谢!

相关文章
相关标签/搜索