querySelector
和querySelectorAll
是新的元素选取方法,返回当前文档中匹配一个特定选择器的所有的元素,使用深度优先、前序遍历规则遍历所有文档节点 。现在所有的浏览器厂商,包括IE8,都提供了 querySelector
和 querySelectorAll
这两个方法的支持。
语法
element = baseElement.querySelector(selectors)
- element 是第一个匹配的DOM节点对象。
- baseElement是一个DOM对象。
- selectors 是一个字符串,包含一个或是多个 CSS 选择器 ,多个则以逗号分隔。
elementList = baseElement.querySelectorAll(selectors)
- elementList 是匹配而且non-live的NodeList对象。
- baseElement是一个DOM对象。
- selectors 是一个字符串,包含一个或是多个 CSS 选择器 ,多个则以逗号分隔。
selectors 的写法与JQuery比较接近,比如
document.querySelector("div.test>p:first-child")
假设一个HTML页面的body如下:
<body> <div id="outside"> <div id="my-id"> <div id="inside"> <div class="lonely"></div> <div class="outer"> <div class="inner">div1</div> <div class="inner">div2</div> </div> </div> </div> </div> </body>
document.querySelector("#my-id .outer .inner")
可得到<div class="inner">div1</div>
document.querySelectorAll("#my-id .outer .inner")
可得到2个class="inner"
的div非实时
querySelector
返回的nodeList是非实时non-live的,指已经获取的nodeList集合不会随着DOM的改变而改变,请看图
即使添加了div也不会改变innerList的值,说明querySelector获取的结果是非实时的。可以对比一个实时的API
childNodes
奇怪之处
还是这个HTML
<body> <div id="outside"> <div id="my-id"> <div id="inside"> <div class="lonely"></div> <div class="outer"> <div class="inner">div1</div> <div class="inner">div2</div> </div> </div> </div> </div> </body>
我们知道获取inner可以先获取outer,再获取里面的inner,即
document.getElementsByClassName('outer')[0].getElementsByClassName('inner')[0]
上面表示先获取outer的第一个DOM元素,再获取outer内的第一个inner元素。
但是querySelector似乎并不是这样的套路,看图
这结果就很有意思,在res2的计算中,
querySelector('#my-id .outer .inner')
并不是从前面的querySelector('.outer')
开始寻找内部。我们再来研究一下
这似乎表示,当querySelector连续使用,是从右往左检测的?
比如res2,先执行
querySelector('#my-id .outer')
找到<div class="outer"></div>
,再判断这个outer
是不是querySelector('#inside')
的后代元素,再判断是不是document
的后代元素。 经过从右往左一系列判断都返回true,则返回res2 为<div class="outer"></div>
又如res3,先执行右边的
querySelector('#inside')
找到<div id="inside"></div>
,再判断这个inside
是不是左边querySelector('#inside')
的后代元素,显然不是。 于是返回null翻阅了相关资料后,这篇文章是这样说的:
这是因为,element.querySelectorAll不是从element开始匹配元素的。而事实上,它会在element的子代元素中匹配查询条件。
我们要记住,querySelector/querySelectorAll下的CSS选择器是绝对的。它们并不会相对于任何特定的元素,甚至不会相对于调用querySelectorAll的元素。总的来说,DOM规范不是总是清晰明了的。了解像这些坑很重要,因为从它们的行为中很难了解它们的实质特性。幸运的是,你可以重写你的选择器,所以没什么关系。如果你无法重写选择器,这里会有一些实现库为你提供你要的现代API。另外,类似jQuery的库会为你提供一套稳定的友好的接口来查找DOM元素。
我也看不太懂这表达了什么……