w3 2006 年就推出了w3 selectors-api 标准,目前支持的浏览器还不多.
今天在chrome和Firefox 3.1下做了一个测试,结果让我很迷惑
?
<html xmlns="http://www.w3.org/1999/xhtml"> <head> <title>Selectors API Example</title> </head> <body> <span>body span1</span> <span>body span2</span> <div id='bar'> <span>span1</span> <div> <span>span2</span> </div> </div> </body> </html>
?
alert(document.getElementById('bar').querySelectorAll('div span').length);//2
?而目前常用的javascript框架中的选择器使用:jQuery举例
alert($('div span','#bar').length);//1
很明显w3的标准在匹配选择符的时候首先把查询范围的Element也包括进去了,而目前的框架是在查询范围的Element的子节点查找的.可是这样的话如果按w3的标准想要剔除这个范围的Element的话,上面的例子就要写成
alert(document.getElementById('bar').querySelectorAll('div div span').length);//1
也许还有其他的写法.
如果只想选择span1的话
//第一种情况,范围没有确定,也就是一个selector表达式下 document.querySelectorAll('#bar>span').length;//1 $('#bar>span').length;//1 //第二种情况,范围已经确定, $('>span','#bar').length;//1 document.querySelectorAll('span',document.querySelector('#bar').length;//2 document.querySelectorAll('>span',document.querySelector('#bar').length;//出错了,不能这样写
我不知道是否是chrome 和Firefox 3.1 的实现有问题.还是他们都太按标准来了.
从某种程度上讲,w3把查询范围的Element也包括进去不是什么大问题,毕竟这是标准,大家习惯了就行了,可是
不支持 '>span'
这种写法就有问题了.如果其他的浏览器在实现上也这样做的话,那么这个标准就形同虚设了.
更进一步的测试:
document.getElementById('bar').querySelectorAll('*').length;//3,这次不包括查询范围了. document.getElementById('bar').querySelectorAll('* div span').length;//2,又包括了 document.getElementById('bar').querySelectorAll('#bar').length;//0,又不包括了
事情更复杂了,选择器可以很复杂,但是对于范围的确定不应该有二义性.
======PS======
经过思考和hax的回复,终于搞清楚了,w3 设计的这个selectors-api是个
纯支持CSS selectors
同时标题也应该改改了
他要达到的是和在样式表里面写的css选择到的 elements 完全一致的结果。
而我们在写程序的时候和这个情形不一样,因为写css的时候是一次完成的,初始范围是整个document的所有节点.
写程序的时候,是有中间过程的,一次选择后的结果会被再一次做为初始范围。这和上面的就不同了。
用hax的描述说就是
这样看来,还是要依靠像jQuery
这样的选择器一阵子了
===来自hax的测试代码===
document.querySelectorAll('span').length;//4 bar.querySelectorAll('span').length;//2 document.querySelectorAll('body span').length;//4 bar.querySelectorAll('body span').length;//仍然是2而 $('body span', bar);//则返回 null
所以 bar.querySelectorAll('body span') 的意思是
符合 body span 并且属于 bar 的子树的节点。
而 $('body span', bar) 表示的是
以bar为context,匹配 body span ,也就是相当于:
document.querySelectorAll('#bar body span')
?
?
?
W3C的Selectors API的两个方法始终都是针对整个document的。
elem.querySelectorAll(s)
等价于(按JS 1.7的写法)
[node for each (node in document.querySelectorAll(s))
if (elem.compareDocumentPosistion(node) & Node.DOCUMENT_POSITION_CONTAINS)]
表示所有match的节点中属于elem的subtree的节点。
它与jquery的函数的第二个参数指定context的语义是不同的。
<body>
<div>
<span>...</span>
<span>...</span>
</div>
<div id="bar">
...
</div>
</body>
此时,
document.querySelectorAll('span')
应该返回4个span。
bar.querySelectorAll('span')
应该返回2个span。
但是注意,后者的意思和 $('span', bar) 不是一回事情。
我们换成下面这样就知道了:
document.querySelectorAll('body span')
应该返回4个span。
bar.querySelectorAll('body span')
还是返回2个span。
而 $('body span', bar) 则返回 null。
所以 bar.querySelectorAll('body span') 的意思是
符合 body span 并且属于 bar 的子树的节点。
而 $('body span', bar) 表示的是
以bar为context,匹配 body span ,也就是相当于:
document.querySelectorAll('#bar body span')