querySelector和querySelectorAll

querySelectorquerySelectorAll是新的元素选取方法,返回当前文档中匹配一个特定选择器的所有的元素,使用深度优先、前序遍历规则遍历所有文档节点 。现在所有的浏览器厂商,包括IE8,都提供了 querySelectorquerySelectorAll这两个方法的支持。

  • 语法

    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的改变而改变,请看图
    non-live

    即使添加了div也不会改变innerList的值,说明querySelector获取的结果是非实时的。可以对比一个实时的API childNodes
    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似乎并不是这样的套路,看图
    querySelector

    这结果就很有意思,在res2的计算中,querySelector('#my-id .outer .inner')并不是从前面的querySelector('.outer')开始寻找内部。

    我们再来研究一下
    querySelector2

    这似乎表示,当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元素。

    我也看不太懂这表达了什么……

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值