前面的话

  尽管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. AutoMapper对internal访问级别属性的映射

    最近在使用DDD重新搭建公司内部OA的架构,具体情况搭好了应该会写一下,这里说的是今天遇到的问题. 先简单说一下相关的几个部分: 1.聚合.聚合分成了两个模块:一个包含审批单据等估计至少今年不会怎么变 ...

  2. 20150912华为机考2之&quot;输入一段字符串(英文),将每个单词首字母大写后输出&quot;

    还有其他一些(隐性)要求(要不然无法通过测试): .如果首字母已经大写,则不用变 .不是英文字母的不变 e.g. Input: hello world! this is _Ljj speaking! ...

  3. mysql之——存储过程 + 游标 + 事务

    下面是自己曾经编写过的mysql数据库存储过程,留作存档,以后用到的时候拿来参考. 其中,涉及到了存储过程.游标(双层循环).事务. [说明]:代码中的注释只针对当时业务而言,无须理会. 代码如下: ...

  4. java 对象数组定义

    下面代码实现了定义一个数组对象 public class Student { private String username; private int num; public Student(Stri ...

  5. GDB调试之暂停

    暂停机制: 有3种方式可以通知GDB暂停程序的执行. a.断点: 通知GDB在程序中的特定位置暂停执行: b.监视点:通知GDB当特定内存位置(或者涉及一个或多个位置的表达式)的值发生变化时暂停执行: ...

  6. 如何在Android Studio中指定NDK位置?

    如何在Android Studio中指定NDK位置? 问题描述 NDK已经手工下载解包在本地: D:\Portable\android-ndk-r13b 每次创建支持C++项目时,都提示NDK没配置, ...

  7. vue/cli3 配置相对路径

    根目录下新建 vue.config.js 文件 const path = require('path') function resolve(dir){ return path.join(__dirna ...

  8. 【洛谷P4318】完全平方数

    题目大意:求第 K 个无平方因子数. 题解:第 k 小/大的问题一般采用二分的方式,通过判定从 1 到当前数中满足某一条件的数有多少个来进行对上下边界的转移. 考虑莫比乌斯函数的定义,根据函数值将整数 ...

  9. Luffy之注册认证(容联云通讯短信验证)

    用户的注册认证 前端显示注册页面并调整首页头部和登陆页面的注册按钮的链接. 注册页面Register,主要是通过登录页面进行改成而成. 先构造前端页面 <template> <div ...

  10. IDEA 之 “There is no configured/running web-servers found!...”

    首次配置 IDEA 2017.1.1 与 Tomcat9.0 的 java 开发环境. 在配置成功并创建第一个 Web Application(3.1) 项目后,运行或调试正常运行. 直接在 jsp ...