浏览器渲染原理

什么是DOCTYPE及做用
DTD是一系列的语法规则,用来定义XML或(X)HTML的文件类型。浏览器会使用它来判断文档类型,决定使用何种协议来解析,以及切换浏览器模式。
DOCTYPE是用来声明文档类型和DTD规范的,一个主要的做用是文件的合法性验证。若是文件代码不合法,那么浏览器解析时便会出一些差错。
浏览器的工做流程浏览器

  • 解析HTML,生成DOM树,解析CSS生产CSSOM
  • 根据生成的DOM和CSSOM构建渲染树Render tree
  • 根据渲染树,计算每一个节点在屏幕上的位置,尺寸等信息。
  • 将渲染树绘制到屏幕上

注意:渲染对象和Dom元素相对应,但这种对应关系不是一对一的,不可见的Dom元素不会被插入渲染树,例如head元素。另外,display属性为none的元素也不会在渲染树中出现(visibility属性为hidden的元素将出如今渲染树中)。
重排(reflow)和重绘(repaint)
当页面元素的几何属性发生改变时会发生重排,当元素的属性的该变没有影响到几何属性时发生重绘。重排必定会发生重绘,但重绘不必定会引发重排。
何时发生重排缓存

  • 添加或删除可见的DOM元素
  • 元素位置发生该变
  • 元素的尺寸发生该变(包括:外边距,内边距,边框厚度,宽度,高度等属性)
  • 内容改变,例如文本内容该变,或图片被另一张不一样尺寸的图片代替
  • 页面渲染器初始化

因为每次重排都会产生计算消耗,大多数浏览器经过队列化修改并批量执行来优化重排过程,获取布局信息的操做会致使队列刷新,以下面的这些属性和方法须要返回最新的布局信息,因此浏览器会刷新渲染队列并引起重排,应尽可能避免使用。布局

  • clientWidth、clientHeight、clientTop、clientLeft
  • offsetWidth、offsetHeight、offsetTop、offsetLeft
  • scrollWidth、scrollHeight、scrollTop、scrollLeft
  • scrollIntoView()、scrollIntoViewIfNeeded()
  • getComputedStyle()
  • getBoundingClientRect()
  • scrollTo()

何时发生重绘
当页面中元素样式的该变不影响布局时,发生重绘。好比:该变color,background,visibility等
思考下面两段代码:
代码一:性能

var foo = document.getElementById('fooBar');
foo.style.color = 'blue';
foo.style.marginTop = '30px';

代码二:优化

var foo = document.getElementById('fooBar');
foo.style.color = 'blue';
var margin = parseInt(foo.style.marginTop);
foo.style.marginTop = (margin + 10) + 'px';

上面两端代码分别发生多少次重排和重绘?
代码一:一次重排和重绘;代码二:一次重排和一次重排和重绘
为何会这样呢?
当修改一个DOM节点时,修改的操做会先缓存到队列,队列中的修改会在下次UI线程执行时批量更新。修改过的节点会被标记为‘脏’(Dirty),获取脏节点的属性会致使队列中的更新操做马上执行。因此第二段代码的不一样之处在于var margin = parseInt(foo.style.marginTop);引起了一次重排。
如何减小重排和重绘的次数动画

  • 避免对同一个DOM节点进行读和写操做的交叉进行。
  • 使用display:none临时从文档中移除,添加完元素后在显示它
  • 使用document fragment
  • 为须要修改的节点建立一个备份,而后对副本进行操做,修改完后用其代替旧节点(cloneNode)
  • 使用position为absolute或fixed的元素建立动画
  • window.requestAnimation()
  • 虚拟DOM库

参考资料:
How browsers work
《高性能JavaScript》线程