HTML5技术

浏览器内部工作原理 - wangwen896(8)

字号+ 作者:H5之家 来源:H5之家 2016-10-29 15:00 我要评论( )

static bool operator (CSSRuleData r1, CSSRuleData r2) { int spec1 = r1.selector()-specificity(); int spec2 = r2.selector()-specificity(); return (spec1 == spec2) : r1.position() r2.position() : spec1

static bool operator >(CSSRuleData& r1, CSSRuleData& r2)
{
int spec1 = r1.selector()->specificity();
int spec2 = r2.selector()->specificity();
return (spec1 == spec2) : r1.position() > r2.position() : spec1 > spec2;
}

  逐步处理Gradual process

  webkit使用一个标志位标识所有顶层样式表都已加载,如果在attch时样式没有完全加载,则放置占位符,并在文档中标记,一旦样式表完成加载就重新进行计算。

  五、布局(Layout)

  当渲染对象被创建并添加到树中,它们并没有位置和大小,计算这些值的过程称为layout或reflow。

  Html使用基于流的布局模型,意味着大部分时间,可以以单一的途径进行几何计算。流中靠后的元素并不会影响前面元素的几何特性,所以布局可以在文档中从右向左、自上而下的进行。也存在一些例外,比如html tables。

  坐标系统相对于根frame,使用top和left坐标。

  布局是一个递归的过程,由根渲染对象开始,它对应html文档元素,布局继续递归的通过一些或所有的frame层级,为每个需要几何信息的渲染对象进行计算。

  根渲染对象的位置是0,0,它的大小是viewport-浏览器窗口的可见部分。

  所有的渲染对象都有一个layout或reflow方法,每个渲染对象调用需要布局的children的layout方法。

  Dirty bit系统

  为了不因为每个小变化都全部重新布局,浏览器使用一个dirty bit系统,一个渲染对象发生了变化或是被添加了,就标记它及它的children为dirty——需要layout。存在两个标识——dirty及children are dirty,children are dirty说明即使这个渲染对象可能没问题,但它至少有一个child需要layout。

  全局和增量layout

  当layout在整棵渲染树触发时,称为全局layout,这可能在下面这些情况下发生:

  1. 一个全局的样式改变影响所有的渲染对象,比如字号的改变。

  2. 窗口resize。

  layout也可以是增量的,这样只有标志为dirty的渲染对象会重新布局(也将导致一些额外的布局)。增量layout会在渲染对象dirty时异步触发,例如,当网络接收到新的内容并添加到Dom树后,新的渲染对象会添加到渲染树中。

图20:增量layout

  异步和同步layout

  增量layout的过程是异步的,Firefox为增量layout生成了reflow队列,以及一个调度执行这些批处理命令。WebKit也有一个计时器用来执行增量layout-遍历树,为dirty状态的渲染对象重新布局。

  另外,当脚本请求样式信息时,例如“offsetHeight”,会同步的触发增量布局。

  全局的layout一般都是同步触发。

  有些时候,layout会被作为一个初始layout之后的回调,比如滑动条的滑动。

  优化

  当一个layout因为resize或是渲染位置改变(并不是大小改变)而触发时,渲染对象的大小将会从缓存中读取,而不会重新计算。

  一般情况下,如果只有子树发生改变,则layout并不从根开始。这种情况发生在,变化发生在元素自身并且不影响它周围元素,例如,将文本插入文本域(否则,每次击键都将触发从根开始的重排)。

  layout过程

  layout一般有下面这几个部分:

  1. parent渲染对象决定它的宽度

  2. parent渲染对象读取chilidren,并:

    a. 放置child渲染对象(设置它的x和y)

    b. 在需要时(它们当前为dirty或是处于全局layout或者其他原因)调用child渲染对象的layout,这将计算child的高度

    c. parent渲染对象使用child渲染对象的累积高度,以及margin和padding的高度来设置自己的高度-这将被parent渲染对象的parent使用

    d. 将dirty标识设置为false

  Firefox使用一个“state”对象(nsHTMLReflowState)做为参数去布局(firefox称为reflow),state包含parent的宽度及其他内容。

  Firefox布局的输出是一个“metrics”对象(nsHTMLReflowMetrics)。它包括渲染对象计算出的高度。

  宽度计算

  渲染对象的宽度使用容器的宽度、渲染对象样式中的宽度及margin、border进行计算。例如,下面这个div的宽度:

  <div />

  webkit中宽度的计算过程是(RenderBox类的calcWidth方法):

  到这里是最佳宽度的计算过程,现在计算宽度的最大值和最小值,如果最佳宽度大于最大宽度则使用最大宽度,如果小于最小宽度则使用最小宽度。最后缓存这个值,当需要layout但宽度未改变时使用。

  Line breaking

  当一个渲染对象在布局过程中需要折行时,则暂停并告诉它的parent它需要折行,parent将创建额外的渲染对象并调用它们的layout。

  六、绘制(Painting)

  绘制阶段,遍历渲染树并调用渲染对象的paint方法将它们的内容显示在屏幕上,绘制使用UI基础组件,这在UI的章节有更多的介绍。

  全局和增量

  和布局一样,绘制也可以是全局的——绘制完整的树——或增量的。在增量的绘制过程中,一些渲染对象以不影响整棵树的方式改变,改变的渲染对象使其在屏幕上的矩形区域失效,这将导致操作系统将其看作dirty区域,并产生一个paint事件,操作系统很巧妙的处理这个过程,并将多个区域合并为一个。Chrome中,这个过程更复杂些,因为渲染对象在不同的进程中,而不是在主进程中。Chrome在一定程度上模拟操作系统的行为,表现为监听事件并派发消息给渲染根,在树中查找到相关的渲染对象,重绘这个对象(往往还包括它的children)。

  绘制顺序

  css2定义了绘制过程的顺序——。这个就是元素压入堆栈的顺序,这个顺序影响着绘制,堆栈从后向前进行绘制。

  一个块渲染对象的堆栈顺序是:

  1. 背景色

  2. 背景图

  3. border

  4. children

  5. outline

  Firefox显示列表

  Firefox读取渲染树并为绘制的矩形创建一个显示列表,该列表以正确的绘制顺序包含这个矩形相关的渲染对象。

  用这样的方法,可以使重绘时只需查找一次树,而不需要多次查找——绘制所有的背景、所有的图片、所有的border等等。

  Firefox优化了这个过程,它不添加会被隐藏的元素,比如元素完全在其他不透明元素下面。

  WebKit矩形存储

  重绘前,WebKit将旧的矩形保存为位图,然后只绘制新旧矩形的差集。

  七、动态变化

 

1.本站遵循行业规范,任何转载的稿件都会明确标注作者和来源;2.本站的原创文章,请转载时务必注明文章作者和来源,不尊重原创的行为我们将追究责任;3.作者投稿可能会经我们编辑修改或补充。

相关文章
  • IndexedDB:浏览器里内置的数据库(转) - letvar

    IndexedDB:浏览器里内置的数据库(转) - letvar

    2016-10-26 10:00

  • canvas画布在主流浏览器中的尺寸限制 - 术虫

    canvas画布在主流浏览器中的尺寸限制 - 术虫

    2016-10-16 10:00

  • 前端工作面试问题 - wangwen896

    前端工作面试问题 - wangwen896

    2016-10-03 12:16

  • html5 video.js 使用及兼容所有浏览器 - 小童童

    html5 video.js 使用及兼容所有浏览器 - 小童童

    2016-09-24 15:00

网友点评
p