某某茶叶有限公司欢迎您!
金沙棋牌在线 > Web前端 > 原生DOM选择器querySelector和querySelectorAll

原生DOM选择器querySelector和querySelectorAll

时间:2019-12-29 06:39

DOM元素querySelectorAll可能让你意外的特性表现

2015/11/07 · HTML5 · DOM, querySelectorAll

原文出处: 张鑫旭   

抛砖引玉

在传统的 JavaScript 开发中,查找 DOM 往往是开发人员遇到的第一个头疼的问题,原生的 JavaScript 所提供的 DOM 选择方法并不多,仅仅局限于通过 tag, name, id 等方式来查找,这显然是远远不够的,如果想要进行更为精确的选择不得不使用看起来非常繁琐的正则表达式,或者使用某个库。事实上,现在所有的浏览器厂商都提供了 querySelector 和 querySelectorAll 这两个方法的支持,甚至就连微软也派出了 IE 8 作为支持这一特性的代表,querySelector 和 querySelectorAll 作为查找 DOM 的又一途径,极大地方便了开发者,使用它们,你可以像使用 CSS 选择器一样快速地查找到你需要的节点。

一、时间紧急,废话少说

本文所在的页面藏匿了下面这些代码:

<img id="outside"> <div id="my-id"> <img id="inside"> <div class="lonely"></div> <div class="outer"> <div class="inner"></div> </div> </div>

1
2
3
4
5
6
7
8
<img id="outside">
<div id="my-id">
    <img id="inside">
    <div class="lonely"></div>
    <div class="outer">
        <div class="inner"></div>
    </div>
</div>

就是下面这样的表现(为了便于观察,我加了边框背景色和文字):

图片 1

首先说点大家都知道的热热身。

  • querySelectorquerySelectorAll IE8+浏览器支持。
  • querySelector返回的是单个DOM元素;querySelectorAll返回的是NodeList.
  • 我们一般用的多的是document.querySelectorAll, 实际上,也支持dom.querySelectorAll.例如:
JavaScript

document.querySelector("#my-id").querySelectorAll("img")

<table>
<colgroup>
<col style="width: 50%" />
<col style="width: 50%" />
</colgroup>
<tbody>
<tr class="odd">
<td><div class="crayon-nums-content" style="font-size: 13px !important; line-height: 15px !important;">
<div class="crayon-num" data-line="crayon-5b8f2fbc48034065158916-1">
1
</div>
</div></td>
<td><div class="crayon-pre" style="font-size: 13px !important; line-height: 15px !important; -moz-tab-size:4; -o-tab-size:4; -webkit-tab-size:4; tab-size:4;">
<div id="crayon-5b8f2fbc48034065158916-1" class="crayon-line">
document.querySelector(&quot;#my-id&quot;).querySelectorAll(&quot;img&quot;)
</div>
</div></td>
</tr>
</tbody>
</table>

选择的就是里面这个妹子。例如,我在控制台输出该选择NodeList的长度和id,如下截图:
图片 2

好了,上面都是众所周知的,好,下面开始展示点有意思的。

大家看下下面2行简单的查询语句:

JavaScript

document.querySelectorAll("#my-id div div");

1
document.querySelectorAll("#my-id div div");

JavaScript

document.querySelector("#my-id").querySelectorAll("div div");

1
document.querySelector("#my-id").querySelectorAll("div div");

图片 3

提问:上面两个语句返回的NodeList的内容是否是一样的?

给大家1分钟的时间思考下。

//zxx: 假设1分钟已经过去了

好了,答案是:不一样的。估计不少人跟我一样,会认为是一样的。

实际上:

JavaScript

document.querySelectorAll("#my-id div div").length === 1;

1
document.querySelectorAll("#my-id div div").length === 1;

JavaScript

document.querySelector("#my-id").querySelectorAll("div div").length === 3;

1
document.querySelector("#my-id").querySelectorAll("div div").length === 3;

大家如果有疑问,可以在控制台测试下,下图就是我自己测试的结果:

图片 4

为啥会这样?

第一个符合我们的理解,不解释。那下一个语句,为何返回的NodeList长度是3呢?

首先,遍历该NodeList会发现,查询的三个dom元素为:div.lonelydiv.outerdiv.inner.

奇怪,奇怪,怎么会是3个呢?

jQuery中有个find()方法,大家很可能受到这个方法影响,导致出现了一些认知的问题:

JavaScript

$("#my-id").find("div div").length === 1;

1
$("#my-id").find("div div").length === 1;

如果使用find方法,则是1个匹配;由于结构和作用类似,我们很自然疑问原生的querySelectorAll也是这个套路。真是太错特错!!

要解释,为何NodeList长度是3,只要一句话就可以了,我特意加粗标红:

CSS选择器是独立于整个页面的!

什么意思呢?比如说你在页面很深的一个DOM里面写上:

<style> div div { } </style>

1
2
3
<style>
div div { }
</style>

 

整个网页,包括父级,只要是满足div div父子关系的元素,全部会被选中,对吧,这个大家应该都清楚的。

这里的querySelectorAll里面的选择器也同样是这也全局特性。document.querySelector("#my-id").querySelectorAll("div div")翻译成白话文就是:查询#my-id的子元素,同时满足整个页面下div div选择器条件的DOM元素们。

我们页面往上滚动看看原始的HTML结构,会发现,在全局视野下,div.lonelydiv.outerdiv.inner全部都满足div div这个选择器条件,于是,最终返回的长度为3.

  很多前端类库(比如dojo与JQuery)在涉及dom操作时都会见到两个模块:attr、prop。某天代码复查时,见到一段为某节点设置文本的代码:

  querySelector

二、:scope与区域选择限制

其实,要想querySelectorAll后面选择器不受全局影响,也是有办法的,就是使用目前还处于实验阶段的:scope伪类,其作用就是让CSS是在某一范围内使用。此伪类在CSS中使用是大头,但是也可以在querySelectorAll语句中使用:

JavaScript

document.querySelector("#my-id").querySelectorAll(":scope div div");

1
document.querySelector("#my-id").querySelectorAll(":scope div div");

兼容性如下:

图片 5

我写此文时候是15年11月初,目前基本上就FireFox浏览器支持,我估计,以后,会支持越来越多的。为什么呢?

因为Web Components需要它,可以实现真正独立封装,不会受外界影响的HTML组件。

关于:scope目前支持尚浅,时机未到,我就没必要乱展开了,点到为止。

attr.set(node, 'innerText', 'Hello World!')

querySelector 和 querySelectorAll 的使用非常的简单,就像标题说到的一样,它和 CSS 的写法完全一样,对于前端开发人员来说,这是难度几乎为零的一次学习。假如我们有一个 id 为 test 的 DIV,为了获取到这个元素,你也许会像下面这样:

三、结语还是要的

参考文章:querySelectorAll from an element probably doesn’t do what you think it does

感谢阅读,欢迎纠错,欢迎交流!

1 赞 1 收藏 评论

图片 6

  这段代码执行后并未生效,虽说innerText不是标准属性,尚未被ff支持,可用的是chrome,这个属性是被支持的。既然显示的文本没变,那就查看一下元素吧。

  document.getElementById("test");

图片 7

现在我们来试试使用新方法来获取这个 DIV:

  innerText被添加到了html标签上,而换成prop模块后,成功的为节点替换文本。

  document.querySelector("#test");
  document.querySelectorAll("#test")[0];

  以上的这个小案例就涉及到了DOM操作时常常被忽略的一个问题:特性与属性的区别

获取文档中 class=”example” 的第一个

 

元素:

 

  document.querySelector("p.example");

返本求源

获取文档中有 “target” 属性的第一个 元素:

    在DOM中,特性指的是html标签上的属性,比如:

  document.querySelector("a[target]");

  图片 8

使用这两个方法无法查找带伪类状态的元素,比如querySelector(':hover')不会得到预期结果。

  Property是对于某一类型特征的描述。可以这样理解,在DOM元素中可以通过点语法访问,又不是标准特性的都可以成为属性。

  querySelectorAll

  DOM中所有的节点都实现了Node接口。Node接口是在DOM1级中定义的,其中定义了一些用来描述DOM节点的属性和操作方法。

该方法返回所有满足条件的元素,结果是个nodeList集合。查找规则与前面所述一样。