浏览器的解析原理

@HuYuee 2017-05-27 14:22:25发表于 iuap-design/blog

浏览器工作流程

先来个流程图,让大家心里有个底:

webkitflow

从上图,我们能看到这几点:

  1. 浏览器会解析
    • HTML生成DOM Tree
    • CSS生成Style Rules
  2. 解析完成后,浏览器引擎会通过DOM Tree 和 CSS Rule Tree 来构造 Render Tree(渲染树)。注意:Render Tree 渲染树并不等于DOM树,因为head元素和一些display:none的元素没有放在渲染树中

浏览器解析

有下面的HTML示例如下:

<html> 
	<body> 
		<div class =“err” id =“div1”> 
			<p> 
              这是一个
              <span class =“big”>大错误</span> 
              这也是一个
              <span class =“big”>非常大的错误</span>错误
        	</p> 
		</div> 
		<div class =“err” id =“div2”>另一个错误</div> 
    </body> 
</html>

然后我们的CSS文档是这样的:

/*1.*/ div {margin:5px; colorblack} 
/*2.*/ .err {colorred} 
/*3.*/ .big {margin-top:3px} 
/*4.*/ div span {margin-bottom:4px} 
/*5.*/ #div1 {color:蓝色} 
/*6.*/ #div2 {colorgreen}

于是我们的CSS Rule Tree是这样:

image027

注意:CSS匹配HTML元素是一个相当复杂和有性能问题的事情。所以,你就会在N多地方看到很多人都告诉你,DOM树要小,CSS尽量用id和class,千万不要过渡层叠下去,……

通过这两个树,我们可以得到一个叫Style Context Tree,也就是下面这样(把CSS Rule结点Attach到DOM Tree上):

image029

这个时候就有必要说下这个CSS选择器特性了

选择器特性

CSS选择器由CSS2规范定义如下:

  • 如果声明来自是“样式”属性,则计数1,否(= a)
  • 计数选择器中的ID属性数(= b)
  • 计数选择器中其他属性和伪类的数量(= c)
  • 计数选择器中元素名称和伪元素的数量(= d)

连接四个数字abcd(在具有大基数的数字系统中)具有特异性。

这个四个数字保持的优先级是:a>b>c>d

您需要使用的数字基数由您在其中一个类别中的最高数量定义。
例如,如果a = 14,您可以使用十六进制基数。在不太可能的情况下,您将需要一个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 * / 
#test {} / * 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 * /