浏览器内部工作原理

浏览器内部工作原理:

参考链接:https://kb.cnblogs.com/page/129756/

渲染引擎首先通过网络获得所请求文档的内容,通常以8K分块的方式完成。

渲染引擎在取得内容之后的基本流程:

解析html以构建dom树 (同步构建css树)-> 构建render树 (可视化dom树)-> 布局render树 -> 绘制render树
为了更好的用户体验,渲染引擎将会解析完一部分内容就显示一部分内容,同时,可能还在通过网络下载其余内容。
渲染树由元素显示序列中的可见元素组成,它是文档的可视化表示,构建这棵树是为了以正确的顺序绘制文档内容。

渲染对象和Dom元素相对应,但这种对应关系不是一对一的,不可见的Dom元素不会被插入渲染树。(display属性为none的元素也不会在渲染树中出现,visibility属性为hidden的元素将出现在渲染树中)

处理脚本及样式表的顺序:
  脚本
  web的模式是同步的,开发者希望解析到一个script标签时立即解析执行脚本,并阻塞文档的解析直到脚本执行完。如果脚本是外引的,则网络必须先请求到这个资源——这个过程也是同步的,会阻塞文档的解析直到资源被请求到。这个模式保持了很多年,并且在html4及html5中都特别指定了。开发者可以将脚本标识为defer,以使其不阻塞文档解析,并在文档解析结束后执行。Html5增加了标记脚本为异步的选项,以使脚本的解析执行使用另一个线程。
  预解析(Speculative parsing)
  Webkit和Firefox都做了这个优化,当执行脚本时,另一个线程解析剩下的文档,并加载后面需要通过网络加载的资源。这种方式可以使资源并行加载从而使整体速度更快。需要注意的是,预解析并不改变Dom树,它将这个工作留给主解析过程,自己只解析外部资源的引用,比如外部脚本、样式表及图片。
  样式表(Style sheets)

  样式表采用另一种不同的模式。理论上,既然样式表不改变Dom树,也就没有必要停下文档的解析等待它们,然而,存在一个问题,脚本可能在文档的解析过程中请求样式信息,如果样式还没有加载和解析,脚本将得到错误的值,显然这将会导致很多问题,这看起来是个边缘情况,但确实很常见。Firefox在存在样式表还在加载和解析时阻塞所有的脚本,而Chrome只在当脚本试图访问某些可能被未加载的样式表所影响的特定的样式属性时才阻塞这些脚本。


风趣版本:

HTML页面加载和解析流程 
1. 用户输入网址(假设是个html页面,并且是第一次访问),浏览器向服务器发出请求,服务器返回html文件; 
2. 浏览器开始载入html代码,发现<head>标签内有一个<link>标签引用外部CSS文件; 
3. 浏览器又发出CSS文件的请求,服务器返回这个CSS文件; 
4. 浏览器继续载入html中<body>部分的代码,并且CSS文件已经拿到手了,可以开始渲染页面了; 
5. 浏览器在代码中发现一个<img>标签引用了一张图片,向服务器发出请求。此时浏览器不会等到图片下载完,而是继续渲染后面的代码; 
6. 服务器返回图片文件,由于图片占用了一定面积,影响了后面段落的排布,因此浏览器需要回过头来重新渲染这部分代码; 
7. 浏览器发现了一个包含一行Javascript代码的<script>标签,赶快运行它; 
8. Javascript脚本执行了这条语句,它命令浏览器隐藏掉代码中的某个<div> (style.display=”none”)。突然少了这么一个元素,浏览器不得不重新渲染这部分代码; 
9. 终于等到了</html>的到来,浏览器泪流满面…… 
10. 等等,还没完,用户点了一下界面中的“换肤”按钮,Javascript让浏览器换了一下<link>标签的CSS路径; 
11. 浏览器召集了在座的各位<div><span><ul><li>们,“大伙儿收拾收拾行李,咱得重新来过……”,浏览器向服务器请求了新的CSS文件,重新渲染页面。


重绘重排

参考链接:http://web.jobbole.com/83164/

每次重排,必然会导致重绘,那么,重排会在哪些情况下发生?

  1. 添加或者删除可见的DOM元素
  2. 元素位置改变
  3. 元素尺寸改变
  4. 元素内容改变(例如:一个文本被另一个不同尺寸的图片替代)
  5. 页面渲染初始化(这个无法避免)
  6. 浏览器窗口尺寸改变

大多数浏览器通过队列化修改并批量执行来优化重排过程,一次完成!但是,有些时候你可能会强制刷新队列并要求计划任务立即执行。

获取布局信息的操作会导致队列刷新,比如:

  1. offsetTop, offsetLeft, offsetWidth, offsetHeight
  2. scrollTop, scrollLeft, scrollWidth, scrollHeight
  3. clientTop, clientLeft, clientWidth, clientHeight
  4. getComputedStyle() (currentStyle in IE)

重排和重绘是DOM编程中耗能的主要原因之一,平时涉及DOM编程时可以参考以下几点:

  1. 尽量不要在布局信息改变时做查询(会导致渲染队列强制刷新)
  2. 同一个DOM的多个属性改变可以写在一起(减少DOM访问,同时把强制渲染队列刷新的风险降为0)
  3. 如果要批量添加DOM,可以先让元素脱离文档流,操作完后再带入文档流,这样只会触发一次重排(fragment元素的应用)
  4. 2
    var fragment = document . createDocumentFragment ( ) ;

  5. 将需要多次重排的元素,position属性设为absolute或fixed,这样此元素就脱离了文档流,它的变化不会影响到其他元素。例如有动画效果的元素就最好设置为绝对定位。
重排必然重绘。
使用 fixed 或 absoult 的元素,修改它们CSS 是不会重排( reflow) 的。 
 table 布局很小的一个小改动会造成整个 table 的重新布局 重绘重排

猜你喜欢

转载自blog.csdn.net/panying0903/article/details/80165510