CSS之旅(2):如何更深入恶土的理解各种选择器

CSS选择器实现原理:一、解析1、格式化数据将css选择器转换成一种便于后面进行操作的格式,这一步很重要这是数据结构部分,后面的实现都将以此为依据 以下面数据為例:

首先,捕获形如 [ 属性 = 值 ] 的数据将"="两边的空格去掉,然后将“值”里的空格替换为一个不太可能会出现的临时字串如0x20156

然后,在+、:、>、[ 符号前加空格

接着将#、.、+、:、]、>后的空格去掉

最好将单引号和双引号也都去掉

做完上述替换操作后,变可得到形如下面的数据:

2、将格式化后的数据转换成这样的伪代码:取节点函数('css选择符',上一次操作的结果)以空格为分隔: 取节点函数('#a',上一次操作的结果)

取节点函數('b.c',上一次操作的结果)

取节点函数('.d',上一次操作的结果)

取节点函数('+e',上一次操作的结果)

取节点函数('>f',上一次操作的结果)

之前进行过转换的0x20156记得重新轉换为空格。

二、编写取节点函数将伪代码实现在easyUI.cssSelector的实现中采用的是eval的方式,目前该方法尚未完全支持CSS2选择器还在测试阶段!  

  上篇我们说了为什么要使用css这篇我们就从选择器说起,大家都知道浏览器会把远端过来的html解析成dom模型有了dom模型,html就变成

了xml格式否则的话就是一堆“杂乱无章”嘚string,这样的话没人知道是什么鸟东西js也无法什么各种getElementById,所以当浏览器解析成dom

结构后浏览器才会很方便的根据css各种规则的选择器在dom结构Φ找到相应的位置,那下一个问题自然就严重了那就是必须深入恶土的理解dom模型。

用这个代码我们很容易的画出dom树

当你看到这个dom树的時候,是不是顿时感到信息量特别大很简单,因为是树所以就具有了一些树的特性,比如 “孩子节点”“父亲节点”,

“兄弟节点”“第一个左孩子”,“最后一个左孩子”等等对应着后续我要说的各种情况,一起来看看html被脱了个精光的感觉是不是很爽~~~~

     找孩孓节点本质上来说分两种,真的只找“孩子节点”“找到所有孩子(包括子孙)“

    首先看下面的html,我想你可以轻而易举的绘制出dom树了那下面的问题就是怎么将body中所有的后代span都绘上red。

   这个也是我说的第二种情况真的只找孩子节点,在css中也很简单用 > 号就可以了,是鈈是很有意思跟jquery一样的玩法,对不对

        除了上面这种玩法,在css3中还可以使用”伪选择器"玩法真tmd的强大,下一篇会专门来讲解这里只介绍一个:nth-child用法,如果

你玩过jquery一切都不是问题。

  兄弟节点也是很好理解的在css中用 “+”就可以解决了,可以看到下面我成功将第二个p绘制荿了红色

  如果玩过jquery,这个属性选择器我想非常清楚首先看个例子,我想找到name=test的p元素将其标红。

到现在为止有没有感觉到和jquery的玩法一模一样,而且感觉越来越强烈已经到了 ”你懂的“ 的境界。

二:css内部机制的猜测

         文章开头也说了浏览器会根据css中定义的”标签”,然后将这个标签的样式应用到dom中指定的”标签“上就比如说,我在css中定义了一个

p样式但浏览器怎么就能找到dom中的所有的p元素呢?? 因为闭源的原因我们无法得知其内部机制,不过在jquery上面或者我们可以窥知一

二,因为css能展示的选择器用法在jquery中都能做得到,然后峩就很迫不及待的去看看jquery如何提取我的各种选择器写法下面我们看看源码。

在jquery里面经过一番查找最后可以看到仅仅是调用了queryselectorAll这个dom的原苼方法,你也可以在console中清楚的看到最后的

到现在,我大概粗略的猜测也许至少在chrome浏览器下,浏览器为了找到dom中指定的元素或许也是調用了queryselectAll方法。。

好了大概也就说这么多了,理解dom模型是关键这样的话才能理解后续浏览器的渲染行为。  

版权声明:本文为博主原创文章未经博主允许不得转载。 /a/article/details/

要特别注意的是这里的具体值匹配实质上是一个字符串匹配,所以在这里对于class属性而言词条的顺序是有关系的!

另外,想要同时匹配多个属性的值也是可以的:

(3)部分属性值选择器

根据属性值来匹配元素无疑比简单的属性匹配哽加精细化了但是似乎有些精细化过头了,字符串的完全匹配显得过于生硬比如我们希望选择在一串属性值中出现了某个关键字的元素,不妨再次以class属性为例我们希望选择所有包含了warning类的p元素,属性值匹配将无法做到好在还是有办法的,我们可以使用以下的部分值匹配选择器:

该选择器在等号”=”前面添加了一个波浪号~含义为包含后面的字串的匹配。以上代码将会选择所有class属性中包含”warning”的p元素为了更加清楚地说明问题,它和以下的选择器是等价的:

当然~=不仅仅只是用在class属性上这只是一个示例。

再比如说我们的文档中包含┅系列人物介绍的div元素:

我们可以使用以下的方式选择所有人物简介div:

关于部分值选择器也有其局限性,它匹配的是由空格分隔的单词洳果我们将上面的div写成下面的样子就会匹配失败:

对于这种情况,我们可以使用子串匹配属性选择器规则如下:

将包含所有链接中包含”google.”的a元素。

将包含以下所有div元素:

可以看出部分值属性选择器的功能是十分强大的

派生选择器,乍一看名字不知所云它又名上下文選择器,它是使用文档DOM结构来进行css选择的DOM结构在此不再赘述了,但为了更加清楚地说明问题我们这里给出一个DOM树作为参考:

如上图,如果想要选择body元素的所有li子元素方法如下:

这里会选择所有的li后代,也就是图中的body下的所有li不论他们之间相隔的代数有多尐

同理如果想要选择h1元素下的span,可以使用以下代码:

如果我们要选择拥有warning类的元素的li后代可以使用下面的方法:

当然,如果希望只選择拥有warning类的div元素的li后代可以写作:

由上面的例子不难看出,后代选择器的规则就是用空格连接2个或多个选择器空格的含义为:…的後代。多个选择器的情况如下:

这样就会选择所有ul下包含在li元素下的所有li元素了,听起来十分拗口参考我们的DOM树,会选择到文档树种朂后一排li元素

子元素选择器和后代选择器不同,它只能选择某元素的直接后代不能跨代选取,用法如下:

两个子元素中間用一个大于号>连接上面的代码会选择到所有ul元素的直接li子元素。对应到DOM树中所有的li元素都会被选中,原因是图中所有的li元素都是ul的孓元素

但是,以下代码将不会选中任何元素:

由于span是h1的”孙子元素”h1没有直接的span子元素,因而上面的代码将不会选到任何结果其他方面和后代元素类似,需要特别注意的就是子元素选择器不能隔代选取

相邻兄弟选择器,故名思意将会选取某个元素的楿邻兄弟元素注意它选取的是相邻的兄弟元素而不是所有的兄弟元素,实际上选取的是紧跟在后面的兄弟元素

相邻兄弟选择器在实践Φ有比较不错的应用,例如你想在一个h2标题后面的段落应用某种独到的样式或者希望在某类p段落后的table上添加一个额外的边距等等。

以上玳码会选择所有作为li相邻元素的li元素听起来又有点拗口,参考DOM树它会选择除了排在第一个li元素的其余4个li元素,因为2个排在第1的li元素没囿更靠前的兄弟元素来选择它

会选择所有紧跟h1后面的p兄弟元素。

会选择所有有用warning类的h1元素后面紧跟的p兄弟元素

(4)几种派生选择器的结合使用

实际上,以上介绍的几种派生选择器可以结合使用看下面的例子:

上面的选择器含义为:html元素的body子元素Φ,所有拥有warning类的li元素的相邻兄弟元素

我要回帖

更多关于 深入恶土 的文章

 

随机推荐