HTML5技术

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

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

处理html和body标签将构建渲染树的根,这个根渲染对象对应被css规范称为containing block的元素——包含了其他所有块元素的顶级块元素。它的大小就是viewport——浏览器窗口的显示区域,Firefox称它为viewPortFrame

  处理html和body标签将构建渲染树的根,这个根渲染对象对应被css规范称为containing block的元素——包含了其他所有块元素的顶级块元素。它的大小就是viewport——浏览器窗口的显示区域,Firefox称它为viewPortFrame,webkit称为RenderView,这个就是文档所指向的渲染对象,树中其他的部分都将作为一个插入的Dom节点被创建。

  样式计算(Style Computation)

  创建渲染树需要计算出每个渲染对象的可视属性,这可以通过计算每个元素的样式属性得到。

  样式包括各种来源的样式表,行内样式元素及html中的可视化属性(例如bgcolor),可视化属性转化为css样式属性。

  样式表来源于浏览器默认样式表,及页面作者和用户提供的样式表——有些样式是浏览器用户提供的(浏览器允许用户定义喜欢的样式,例如,在Firefox中,可以通过在Firefox Profile目录下放置样式表实现)。

  计算样式的一些困难:

  1. 样式数据是非常大的结构,保存大量的样式属性会带来内存问题。

  2. 如果不进行优化,找到每个元素匹配的规则会导致性能问题,为每个元素查找匹配的规则都需要遍历整个规则表,这个过程有很大的工作量。选择符可能有复杂的结构,匹配过程如果沿着一条开始看似正确,后来却被证明是无用的路径,则必须去尝试另一条路径。

  例如,下面这个复杂选择符

  div div div div{…}

  这意味着规则应用到三个div的后代div元素,选择树上一条特定的路径去检查,这可能需要遍历节点树,最后却发现它只是两个div的后代,并不使用该规则,然后则需要沿着另一条路径去尝试

  3. 应用规则涉及非常复杂的级联,它们定义了规则的层次

  我们来看一下浏览器如何处理这些问题:

  共享样式数据(Sharing style data)

  WebkKit节点引用样式对象(渲染样式),某些情况下,这些对象可以被节点间共享,这些节点需要是兄弟或是表兄弟节点,并且:

  1. 这些元素必须处于相同的鼠标状态(比如不能一个处于hover,而另一个不是)

  2. 不能有元素具有id

  3. 标签名必须匹配

  4. class属性必须匹配

  5. 对应的属性必须相同

  6. 链接状态必须匹配

  7. 焦点状态必须匹配

  8. 不能有元素被属性选择器影响

  9. 元素不能有行内样式属性

  10. 不能有生效的兄弟选择器,webcore在任何兄弟选择器相遇时只是简单的抛出一个全局转换,并且在它们显示时使整个文档的样式共享失效,这些包括+选择器和类似:first-child和:last-child这样的选择器。

  Firefox规则树(Firefox rule tree)

  Firefox用两个树用来简化样式计算-规则树和样式上下文树,WebKit也有样式对象,但它们并没有存储在类似样式上下文树这样的树中,只是由Dom节点指向其相关的样式。

图14:Firefox样式上下文树

  样式上下文包含最终值,这些值是通过以正确顺序应用所有匹配的规则,并将它们由逻辑值转换为具体的值,例如,如果逻辑值为屏幕的百分比,则通过计算将其转化为绝对单位。样式树的使用确实很巧妙,它使得在节点中共享的这些值不需要被多次计算,同时也节省了存储空间。

  所有匹配的规则都存储在规则树中,一条路径中的底层节点拥有最高的优先级,这棵树包含了所找到的所有规则匹配的路径(译注:可以取巧理解为每条路径对应一个节点,路径上包含了该节点所匹配的所有规则)。规则树并不是一开始就为所有节点进行计算,而是在某个节点需要计算样式时,才进行相应的计算并将计算后的路径添加到树中。

  我们将树上的路径看成辞典中的单词,假如已经计算出了如下的规则树:

  假如需要为内容树中的另一个节点匹配规则,现在知道匹配的规则(以正确的顺序)为B-E-I,因为我们已经计算出了路径A-B-E-I-L,所以树上已经存在了这条路径,剩下的工作就很少了。

  现在来看一下树如何保存。

  结构化

  样式上下文按结构划分,这些结构包括类似border或color这样的特定分类的样式信息。一个结构中的所有特性不是继承的就是非继承的,对继承的特性,除非元素自身有定义,否则就从它的parent继承。非继承的特性(称为reset特性)如果没有定义,则使用默认的值。

  样式上下文树缓存完整的结构(包括计算后的值),这样,如果底层节点没有为一个结构提供定义,则使用上层节点缓存的结构。

  使用规则树计算样式上下文

  当为一个特定的元素计算样式时,首先计算出规则树中的一条路径,或是使用已经存在的一条,然后使用路径中的规则去填充新的样式上下文,从样式的底层节点开始,它具有最高优先级(通常是最特定的选择器),遍历规则树,直到填满结构。如果在那个规则节点没有定义所需的结构规则,则沿着路径向上,直到找到该结构规则。

  如果最终没有找到该结构的任何规则定义,那么如果这个结构是继承型的,则找到其在内容树中的parent的结构,这种情况下,我们也成功的共享了结构;如果这个结构是reset型的,则使用默认的值。

  如果特定的节点添加了值,那么需要做一些额外的计算以将其转换为实际值,然后在树上的节点缓存该值,使它的children可以使用。

  当一个元素和它的一个兄弟元素指向同一个树节点时,完整的样式上下文可以被它们共享。

  来看一个例子:假设有下面这段html

<html>
<body>
<div>
<p>this is a
<span> big error </span>
this is also a
<span> verybigerror</span>
error
</p>
</div>
<div>another error</div>
</body>
</html>

  以及下面这些规则

1.div {margin:5px;color:black}
2..err {color:red}
3..big {margin-top:3px}
4.div span {margin-bottom:4px}
5.#div1 {color:blue}
6.#div2 {color:green}

  简化下问题,我们只填充两个结构——color和margin,color结构只包含一个成员-颜色,margin结构包含四边。

  生成的规则树如下(节点名:指向的规则)

  上下文树如下(节点名:指向的规则节点)

  假设我们解析html,遇到第二个div标签,我们需要为这个节点创建样式上下文,并填充它的样式结构。

  我们进行规则匹配,找到这个div匹配的规则为1、2、6,我们发现规则树上已经存在了一条我们可以使用的路径1、2,我们只需为规则6新增一个节点添加到下面(就是规则树中的F)。

  然后创建一个样式上下文并将其放到上下文树中,新的样式上下文将指向规则树中的节点F。

 

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

网友点评
>