前面的话

  尽管DOM作为API已经非常完善了,但是为了实现更多的功能,DOM仍然进行了扩展,其中一个重要的扩展就是对选择器API的扩展。人们对jQuery的称赞,很多是由于jQuery方便的元素选择器。除了前面已经介绍过的getElementsByClassName()方法外,DOM拓展了querySelectorAll()、querySelector()和matchesSelector()这3种方法,通过CSS选择符查询DOM文档取得元素的引用的功能变成了原生的API,解析和树查询操作在浏览器内部通过编译后的代码来完成,极大地改善了性能。本文将详细介绍html5新增的3种selector方法

方法

querySelector()

  querySelector()方法接收一个CSS选择符,返回与该模式匹配的第一个元素,如果没有找到匹配的元素,返回null。该方法既可用于文档document类型,也可用于元素element类型。关于CSS选择器的详细内容移步至此

  [注意]IE7-浏览器不支持

<body style="height: 100%;">
<div class="box" id="box" style="height: 200px;">
<ul class="list" style="height:100px">
<li class="in" style="height: 30px;">1</li>
<li class="in" style="height: 30px;" title="test">2</li>
<li class="in" style="height: 30px;">3</li>
</ul>
</div>
<script>
//因为没有.null类名,所以返回null
var oNull = document.querySelector('.null');
console.log(oNull);//null
//通过<body>标签取得元素
var body = document.querySelector("body");
console.log(body.style.height);//100%
//通过id属性取得元素
var oBox = document.querySelector('#box');
console.log(oBox.style.height);//200px
//通过结合元素的类选择器取得元素
var oList = document.querySelector('ul.list');
console.log(oList.style.height);//100px
//通过类名取得元素
var oIn = document.querySelector('.in');
console.log(oIn.innerHTML);//1
//通过属性选择器取得元素
var oTest = body.querySelector('[title="test"]');
console.log(oTest.innerHTML);//2
</script>
</body>

querySelectorAll()

  querySelectorAll()接收一个CSS选择符,返回一个类数组对象NodeList的实例。具体来说,返回的值实际上是带有所有属性和方法的NodeList,而其底层实现则类似于一组元素的快照,而非不断对文档进行搜索的动态查询。这样实现可以避免使用NodeList对象通常会引起的大多数性能问题。只要传给querySelectorAll()方法的CSS选择符有效,该方法都会返回一个NodeList对象,而不管找到多少匹配的元素

  没有匹配元素时,返回空的类数组对象,而不是null

  [注意]IE7-浏览器不支持

<body style="height: 100%;">
<div class="box" id="box" style="height: 200px;">
<ul class="list" style="height:100px">
<li class="in" style="height: 30px;">1</li>
<li class="in" style="height: 30px;" title="test">2</li>
<li class="in" style="height: 30px;">3</li>
</ul>
</div>
<script>
//返回[]
var oNull = document.querySelectorAll('.null');
console.log(oNull);
//取得body元素
var body = document.querySelectorAll("body")[0];
console.log(body.style.height);//100%
//取得所有class为"in"的元素
var oIn = document.querySelectorAll('.in');
for(var i = 0 ; i < oIn.length; i++){
console.log(oIn[i].innerHTML);//1,2,3
}
//取得title属性为test的元素
var oTest = body.querySelectorAll('[title="test"]');
console.log(oTest);//[li.in]
</script>
</body>

matchesSelector()

  matchesSelector()方法接收一个CSS选择符参数,如果调用元素与该选择符相匹配,返回true;否则返回false

  [注意]一般地,使用matches()方法来替代matchesSelector()方法

<body id="test">
<script>
//Uncaught TypeError: document.body.matchesSelector is not a function
console.log(document.body.matchesSelector('#test'));
</script>
</body>

  由于兼容性问题,现在各个浏览器都只支持加前缀的方法。IE9+浏览器支持msMatchesSelector()方法,firefox支持mozMatchesSelector()方法,safari和chrome支持webkitMatchesSelector()方法。所以兼容写法为:

function matchesSelector(element,selector){
if(element.matchesSelector){
return element.matchesSelector(selector);
}
if(element.msMatchesSelector){
return element.msMatchesSelector(selector);
}
if(element.mozMatchesSelector){
return element.mozMatchesSelector(selector);
}
if(element.webkitMatchesSelector){
return element.webkitMatchesSelector(selector);
}
}
<body id="test">
<script>
console.log(matchesSelector(document.body,'#test'));//true
</script>
</body>

非实时

  与getElementById()和getElementsByTagName()方法不同,querySelector()和querySelectorAll()方法得到的类数组对象是非动态实时的

<div id="container">
<div>1</div>
<div>2</div>
</div>
<script>
var container = document.getElementById('container');
var divOne = container.querySelector('div:last-child');
var divAll = container.querySelectorAll('div');
console.log(container.children.length);//2
console.log(divOne.innerHTML);//2
console.log(divAll.length);//2 var newDiv = document.createElement('div');
newDiv.innerHTML = 3;
container.appendChild(newDiv); console.log(container.children.length);//3
//由于querySelector不是实时的,所以其保存的仍然是原来第二个div的值
console.log(divOne.innerHTML);//2
//由于querySelectorAll不是实时的,所以仍然只保存了两个div元素
console.log(divAll.length);//2 console.log(container.querySelector('div:last-child').innerHTML);//3
console.log(container.querySelectorAll('div').length);//3
</script>

缺陷

  selector类方法在元素上调用时,指定的选择器仍然在整个文档中进行匹配,然后过滤出结果集,以便它只包含指定元素的后代元素。这看起来是违反常规的,因为它意味着选择器字符串能包含元素的祖先而不仅仅是所匹配的元素

<div id="container">
<div>1</div>
<div>2</div>
</div>
<script>
var container = document.getElementById('container');
console.log(container.querySelectorAll('div div'));//[div div]
</script>

  按照正常理解,控制台应该返回空的类数组对象,因为id为container的div元素的子元素中,不存在div元素嵌套的情况

  但是,该方法实际返回[div div]。这是因为参数中的选择器包含了元素的祖先

  所以,如果出现后代选择器,为了防止该问题,可以在参数中显式地添加当前元素的选择器

<div id="container">
<div>1</div>
<div>2</div>
</div>
<script>
var container = document.getElementById('container');
console.log(container.querySelectorAll('#container div div'));//[]
console.log(container.querySelectorAll('#container div'));//[div div]
console.log(container.querySelectorAll('div'));//[div div]
</script>

最后

  虽然存在着非实时和参数缺陷的问题,但是瑕不掩瑜,selector类方法的出现极大地简化了查找元素的繁琐操作。而且,它们支持IE8浏览器

  javascript选择器API系列写完了,欢迎交流

深入理解javascript选择器API系列第三篇——h5新增的3种selector方法的更多相关文章

  1. 深入理解javascript选择器API系列第三篇——HTML5新增的3种selector方法

    前面的话 尽管DOM作为API已经非常完善了,但是为了实现更多的功能,DOM仍然进行了扩展,其中一个重要的扩展就是对选择器API的扩展.人们对jQuery的称赞,很多是由于jQuery方便的元素选择器 ...

  2. 深入理解javascript选择器API系列第一篇——4种元素选择器

    × 目录 [1]id属性 [2]标签名 [3]name属性[4]all 前面的话 说到最常见的DOM应用,恐怕就要数取得特定的某个或某组元素的引用了.DOM定义了许多方式来选取元素,包括getElem ...

  3. 深入理解javascript选择器API系列第二篇——getElementsByClassName

    × 目录 [1]使用 [2]classList [3]扩展 前面的话 既然有getElementById()和getElementsByTagName()方法,为什么没有getElementsByCl ...

  4. 深入理解javascript函数进阶系列第三篇——函数节流和函数防抖

    前面的话 javascript中的函数大多数情况下都是由用户主动调用触发的,除非是函数本身的实现不合理,否则一般不会遇到跟性能相关的问题.但在一些少数情况下,函数的触发不是由用户直接控制的.在这些场景 ...

  5. javascript面向对象系列第三篇——实现继承的3种形式

    × 目录 [1]原型继承 [2]伪类继承 [3]组合继承 前面的话 学习如何创建对象是理解面向对象编程的第一步,第二步是理解继承.本文是javascript面向对象系列第三篇——实现继承的3种形式 [ ...

  6. 深入理解DOM事件类型系列第三篇——变动事件

    × 目录 [1]删除节点 [2]插入节点 [3]特性节点[4]文本节点 前面的话 变动(mutation)事件能在DOM中的某一部分发生变化时给出提示,这类事件非常有用,但都只能使用DOM2级事件处理 ...

  7. 深入理解DOM事件机制系列第三篇——事件对象

    × 目录 [1]获取 [2]事件类型 [3]事件目标[4]事件代理[5]事件冒泡[6]事件流[7]默认行为 前面的话 在触发DOM上的某个事件时,会产生一个事件对象event,这个对象中包含着所有与事 ...

  8. 深入理解脚本化CSS系列第三篇——脚本化CSS类

    前面的话 在实际工作中,我们使用javascript操作CSS样式时,如果要改变大量样式,会使用脚本化CSS类的技术,本文将详细介绍脚本化CSS类 style 我们在改变元素的少部分样式时,一般会直接 ...

  9. 深入理解javascript函数进阶系列第四篇——惰性函数

    前面的话 惰性函数表示函数执行的分支只会在函数第一次调用的时候执行,在第一次调用过程中,该函数会被覆盖为另一个按照合适方式执行的函数,这样任何对原函数的调用就不用再经过执行的分支了.本文将详细介绍惰性 ...

随机推荐

  1. Jquery 获得当前标签的名称和标签属性

    得到标签的名称 $("#name").prop("tagName"); 或者 $("#name")[0].tagName; 注意:1.得到的 ...

  2. ubuntu14 安装及卸载vmware

    原帖http://blog.sina.com.cn/s/blog_73dac6b50101gp4f.html 适用于ubuntu14和vmware player 12.5

  3. ASP.NET Core "完整发布,自带运行时" 到jexus

    一.阅读前须知   1.使用 jexus整合asp.net core的优点:       1)支持多站点,同一端口可以同时支持任何多的asp.net core应用程序:      2)应用程序启动.停 ...

  4. (译)你应该知道的jQuery技巧

    帮助提高你jQuery应用的简单小技巧. 回到顶部按钮 图片预加载 判断图片是否加载完 自动修补破损图像 Hover切换class类 禁用输入 停止正在加载的链接 toggle fade/slide ...

  5. JAAS 是个什么梗

    参考资料 该文中的内容来源于 Oracle 的官方文档.Oracle 在 Java 方面的文档是非常完善的.对 Java 8 感兴趣的朋友,可以从这个总入口 Java SE 8 Documentati ...

  6. ASP.NET MVC 视图(一)

    ASP.NET MVC 视图(一) 前言 从本篇开始就进入到了MVC中的视图部分,在前面的一些篇幅中或多或少的对视图和视图中的一些对象的运用进行了描述,不过毕竟不是视图篇幅说的不全面,本篇首先为大家讲 ...

  7. [Java定时器]用Spring Task实现一个简单的定时器.

    今天做一个项目的的时候需要用到定时器功能.具体需求是: 每个月一号触发一次某个类中的方法去拉取别人的接口获取上一个月份车险过期的用户.如若转载请附上原文链接:http://www.cnblogs.co ...

  8. 动态给textView加图片

    Drawable img = layout.getResources().getDrawable(R.drawable.icon); // 调用setCompoundDrawables时,必须调用Dr ...

  9. angular2系列教程(四)Attribute directives

    今天我们要讲的是ng2的Attribute directives.顾名思义,就是操作dom属性的指令.这算是指令的第二课了,因为上节课的components实质也是指令. 例子

  10. mysql交互式连接&非交互式连接

    交互式操作:通俗的说,就是你在你的本机上打开mysql的客户端,就是那个黑窗口,在黑窗口下进行各种sql操作,当然走的肯定是tcp协议. 非交互式操作:就是你在你的项目中进行程序调用.比如一边是tom ...