#How Broswers Work<二>渲染引擎--script(下)

来源:互联网 发布:淘宝客服操作流程 编辑:程序博客网 时间:2024/06/05 11:31

用规则做更简单的匹配

这里有几种关于样式规则的来源:
1.CSS规则,来至外部文件或在style标签里

`p {color:blue}`

2.内联的样式属性

<p style="color:blue" />

3.HTML中的可见属性(这将映射到相应的样式规则上)

<p bgcolor="blue" />

后面两个很容易匹配到元素,因为它们所拥有的样式属性和html属性可以将元素作为key进行映射。

就像前面问题2所提到的,css的规则匹配可能很狡猾,为了解决这个问题,可以先对规则进行处理,以使其更容易被访问。

解析完样式表后,规则被添加到几个hash映射中,根据选择器的分类,可分为id映射,class映射,tag映射以及其他的一些映射。如果选择器是id,则会被添加到id映射中,如果是class则会被添加到class映射中,以此类比。

这种操作会使元素更容易匹配规则,他没有必有查看每个规则-我们能从映射中提取相关的规则给这个元素,可排除95%没必要的规则,所以在匹配的过程中这些没必要的规则不会被考虑。

让我们看看下面这个样式的例子:

p.error {color:red}#messageDiv {height:50px}div {margin:5px}

第一条规则将被插入class映射,第二条插入id映射,第三条是标签映射。

下面这个html片段:

<p class="error">an error occurred </p><div id=" messageDiv">this is a message</div>

我们首先找到p元素对应的规则,class映射将包含一个“error”的key,找到p.error的规则,div在id映射和标签映射中都有相关的规则,剩下的工作就是找出这些由key对应的规则中哪些确实是正确匹配的。

例如,如果div的规则是

table div {margin:5px}

这也是标签映射产生的,因为key是最右边的选择符,但它并不匹配这里的div元素,因为这里的div没有table祖先。

Webkit和Firefox都会做这个处理。

以正确的级联顺序应用规则

样式对象拥有对应所有可见属性的属性,如果特性没有被任何匹配的规则所定义,那么一些特性可以从parent的样式对象中继承,另外一些使用默认值。

这个问题的产生是因为存在不止一处的定义,这里用级联顺序解决这个问题。

样式表的级联顺序

一个样式属性的声明可能在几个样式表中出现,或是在一个样式表中出现多次,因此,应用规则的顺序至关重要,这个顺序就是级联顺序。根据css2的规范,级联顺序为(从低到高):

  1. 浏览器声明

  2. 用户声明

  3. 作者的一般声明

  4. 作者的important声明

  5. 用户important声明

浏览器声明是最不重要的,用户只有在声明被标记为important时才会覆盖作者的声明。具有同等级别的声明将根据specifity以及它们被定义时的顺序进行排序。Html可视化属性将被转换为匹配的css声明,它们被视为最低优先级的作者规则。

specifity

选择器具体的定义参照CSS2的说明文档,如下:
1. 如果声明来自style属性,而不是一个选择器的规则,则计1,否则计(=a)
2. 计算选择器中id属性的数量(=b)
3. 计算选择器中class及伪类的数量(=c)
4. 计算选择器中元素名及伪元素的数量(=d)
把这四个数字串联一起a-b-c-d将得到specifity。

这里使用的基数由分类中最高的基数定义。例如如果a=14,你可以用16进制,不同情况下,a为17时,则需要使用阿拉伯数字17作为基数。之后的选择器可能会有如下的例子:html body div div p…(17个标签在你的选择器中,这好像不太可能)。

下面这些例子:

*             {}  /* a=0 b=0 c=0 d=0 -> specificity = 0,0,0,0 */ li            {}  /* a=0 b=0 c=0 d=1 -> specificity = 0,0,0,1 */ li:first-line {}  /* a=0 b=0 c=0 d=2 -> specificity = 0,0,0,2 */ ul li         {}  /* a=0 b=0 c=0 d=2 -> specificity = 0,0,0,2 */ ul ol+li      {}  /* a=0 b=0 c=0 d=3 -> specificity = 0,0,0,3 */ h1 + *[rel=up]{}  /* a=0 b=0 c=1 d=1 -> specificity = 0,0,1,1 */ ul ol li.red  {}  /* a=0 b=0 c=1 d=3 -> specificity = 0,0,1,3 */ li.red.level  {}  /* a=0 b=0 c=2 d=1 -> specificity = 0,0,2,1 */ #x34y         {}  /* a=0 b=1 c=0 d=0 -> specificity = 0,1,0,0 */ style=""          /* a=1 b=0 c=0 d=0 -> specificity = 1,0,0,0 */

规则的排序

规则匹配之后,我们要根据级联顺序排序。Webkit对于比较小的链表用冒泡排序,比较大的用归并。webkit实现排序通过为这些规则重写“>”操作符:

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有一个标志位用于确认高层的样式表已经被加载完成。如果样式在需要时没有完全被加载,这在文档中放占位符,等到样式全部被加载,再重新计算相应的值。

0 0