为什么CSS选择器是从右往左解析?,突然看到这个题目。只是觉得,有蹊跷。(有看过浏览器源代码的同学请指教)。下面自己理一理这个问题。
20180704.html
1 |
|
20180704.css
1 | @charset "utf-8"; |
~测试用的代码,不用在意细节~
看图,我也不说啥了。
the Document tree
我们看一下 CSS2.1 2.3 The CSS 2.1 processing model 第4小条, Annotate。
Annotate every element of the document tree by assigning a single value to every
property that is applicable to the target media type.
the annotated document tree
好了,就先到这里。(我们只考虑我们自己写的样式)问题是 怎么得到这 annotated tree
第一种办法
从dom中取一个节点,然后拿这个节点去cssRules匹配。举几个栗子。
- 拿到
html
,啥也没干。(只考虑自己写的样式) - 拿到
div(class="one")
,正好有.one {border-top: 3px solid #123456;}
,标记上去。 - 拿到
p(class="time")
, 哎,有p {text-decoration: underline;}
,标记上去;再往下看,有.little .time {color: cyan;}
,查看一下它的先祖,有.little
存在,标记上去。 - ……
第二种办法
我们拿一个cssRule,去dom中匹配。试一试。
- 拿到
p {text-decoration: underline;}
,那好,dom中那么多p
,全给标记上。 - 拿到
.one [data-weather="rain"] span {color: brown;}
,找到,标记上。 - 拿到
.one .two .three {font-size: 250in;}
,没找到,对不起。
仔细看第一种方法,拿一个节点,去匹配所有cssRules。也就是说我拿所有的cssRules去测试一个节点,然后下一个节点……。这黄花菜都凉了。
我们看第二种方法。我们就有了从左开始还是从右开始匹配的问题。
.one [data-weather="rain"] span {color: brown;}
- ltr:找到
.one
,ok;然后再找子孙[data-weather="rain"]
,ok;然后再找子孙span
,ok。 - rtl:找到
span
,查看先祖条件.one [data-weather="rain"]
,没问题。
.one .two .three {font-size: 250in;}
- ltr:找到
.one
,ok;然后再找.two
,不存在。 - rtl:没有
.three
,不存在。
找到,我们上面用了这个词。怎么找到?我们的栗子简化多了。一般都是遍历dom返回一组节点。比如找到了一组 span
,然后用限制条件,把不合格的剔除出去。这个简单的栗子中,rtl显然比ltr要快,rtl第一步就找到嫌疑节点(不过看看 .three .two .one
,ltr第一步就排除,rtl开始还以为找到了。但这仅仅是我们构造的一个不寻常规则。杠)。复杂的情况下,节点,cssRules数量很大。rtl会具有更大的优势。
我们回头再看.one [data-weather="rain"] span {color: brown;}
,.one .two .three {font-size: 250in;}
,为什么从右边开始?因为我本来就是要找 span
, .three
,它们自身就处于右边(当然,还要进行过滤,满足前面的限制条件)。浏览器也是用从右向左这个策略。浏览器还提供了几个常用的API:document.querySelector,document.querySelectorAll。比如document.querySelector('.one [data-weather="rain"] span')
我们就能轻易的找到 <span>雨</span>
所代表的节点。
这也就是用一个selector,怎么找到匹配的节点。Sizzle 就是干这个事情的(没用过,没看过,听别人说的)。暂时,我觉得document.querySelector,document.querySelectorAll,document.getElement*,够用了。