一道面试题是如何引发深层次的灵魂拷问? (7)

(2)Repaint,即重绘。意味着元素发生的改变只是影响了元素的一些外观之类的时候(例如,背景色,边框颜色,文字颜色等),此时只需要应用新样式绘制这个元素就可以了。

回流的成本开销要高于重绘,而且一个节点的回流往往回导致子节点以及同级节点的回流, 所以优化方案中一般都包括,尽量避免回流。

6、什么引起回流

1.页面渲染初始化

2.DOM 结构改变,比如删除了某个节点

3.render 树变化,比如减少了 padding

4.窗口 resize

5.最复杂的一种:获取某些属性,引发回流,
很多浏览器会对回流做优化,会等到数量足够时做一次批处理回流,
但是除了 render 树的直接变化,当获取一些属性时,浏览器为了获得正确的值也会触发回流,这样使得浏览器优化无效,包括

(1) offset(Top/Left/Width/Height) (2) scroll(Top/Left/Width/Height) (3) cilent(Top/Left/Width/Height) (4) width,height (5) 调用了getComputedStyle()或者IE的currentStyle

回流一定伴随着重绘,重绘却可以单独出现。

优化方案:

(1)减少逐项更改样式,做好一次性更改样式。或者将样式定义为 class,并一次性更新。

(2)避免循环操作 dom,创建一个 documentFragment 或 div,在他上面进行所有的 dom 操作,最后添加到 window.document 中。

(3)避免多次读取 offset 等属性,无法避免就将他们缓存到变量中。

(4)将复杂的元素绝对定位或者固定定位,使他们脱离文档流,否则回流代价很高。

注意:改变字体大小会引起回流。

再看一个例子:

var s = document.body.style; s.padding = "2px"; // 回流+重绘 s.border = "1px solid red"; // 再一次 回流+重绘 s.color = "blue"; // 再一次重绘 s.backgroundColor = "#ccc"; // 再一次 重绘 s.fontSize = "14px"; // 再一次 回流+重绘 // 添加node,再一次 回流+重绘 document.body.appendChild(document.createTextNode('abc!')); 7、简单层和复合层

上述中的渲染中止步于绘制,但实际上绘制这一步也没有这么简单,它可以结合复合层和简单层的概念来讲。

简单介绍下:

(1)可以默认只有一个复合层,所有的 DOM 节点都是在这个复合图层下。

(2)如果开启了硬件加速功能,可以将某一个节点变成复合图层。

(3)复合图层之间的绘制互不干扰,直接 GPU 直接控制。

(4)简单图层中,就算是 absolute 等布局,变化时不影响整体回流,但是由于在同一个图层中,仍然会影响绘制的,因此做动画时候性能仍然很低。而且复合层是独立的,所以一般做动画推荐使用硬件加速。

更多参考:

8、Chrome 的调试

Chrome 的开发者工具中,Performance 中可以看到详细的渲染过程:

image

image

9、资源外链的下载

上面介绍了 html 解析,渲染流程。但实际上,在解析 html 时,会遇到一些资源连接,此时就需要进行单独处理了。

简单起见,这里将遇到的静态资源分为一下几大类(未列举所有):

遇到外链的处理

css 样式资源

js 脚本资源

img 图片类资源

以下针对每种情况进行详细说明:

遇到外链的处理

当遇到上述的外链时,会单独开启一个下载线程去下载资源(http1.1 中是每一个资源的下载都要开启一个 http 请求,对应一个 tcp/ip 链接)

遇到 css 样式资源

css 资源处理特点:

(1)css 下载时异步的,不会阻塞浏览器构建 DOM 树;

(2)但是会阻塞渲染,也就是在构建 render 树时,等到 css 下载解析后才进行(与浏览器优化有关,防止 css 规则不断变化,避免重复的构建)

(3)有例外,遇到 media query 声明的 css 是不会阻塞构建 render 树

遇到 js 脚本资源

JS 脚本资源的处理有几个特点:

(1)阻塞浏览器的解析,也就是说发现一个外链脚本时,需等待脚本下载完成并执行后才会继续解析 HTML。

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/wsszjw.html