转载

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

一、时间紧急,废话少说

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

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

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

孤家寡人
outer-inner之间
最内部

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

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

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

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

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

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

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

DOM元素querySelectorAll可能让你意外的特性表现 提问:上面两个语句返回的 NodeList 的内容是否是一样的?

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

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

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

实际上:

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

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

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

为啥会这样?

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

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

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

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

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

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

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

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

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

<style> div div { } </style>

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

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

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

二、:scope与区域选择限制

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

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

兼容性如下:

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

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

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

三、结语还是要的

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

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

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

//众人: 你丫逗我呢,这也能叫结语……

本文为原创文章,包含脚本行为,会经常更新知识点以及修正一些错误,因此转载请保留原出处,方便溯源,避免陈旧错误知识的误导,同时有更好的阅读体验。

本文地址: http://www.zhangxinxu.com/wordpress/?p=5036

(本篇完)

相关文章
  • 伪元素表单控件默认样式重置与自定义大全 (0.574)
  • jQuery诞生记-原理与机制 (0.359)
  • 遐想:如果没有IE6和IE7浏览器... (0.354)
  • 近期手机网页项目一些杂碎心得分享 (0.287)
  • jQuery与MooTools库的一些比对 (0.139)
  • JavaScript实现图片幻灯片滚动播放动画效果 (0.072)
  • jQuery之addClasas与removeClass使用实例 (0.072)
  • 翻译:让网络更快一些——最小化浏览器中的回流(reflow) (0.072)
  • JavaScript实现新浪微博文字放大显示动画效果 (0.072)
  • 团购类网站倒计时的js实现 (0.072)
  • HTML5 DOM元素类名相关操作API classList简介 (RANDOM - 0.072)
正文到此结束
Loading...