深入理解javascript选择器API系列第三篇——h5新增的3种selector方法
前面的话
尽管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方法的更多相关文章
- 深入理解javascript选择器API系列第三篇——HTML5新增的3种selector方法
前面的话 尽管DOM作为API已经非常完善了,但是为了实现更多的功能,DOM仍然进行了扩展,其中一个重要的扩展就是对选择器API的扩展.人们对jQuery的称赞,很多是由于jQuery方便的元素选择器 ...
- 深入理解javascript选择器API系列第一篇——4种元素选择器
× 目录 [1]id属性 [2]标签名 [3]name属性[4]all 前面的话 说到最常见的DOM应用,恐怕就要数取得特定的某个或某组元素的引用了.DOM定义了许多方式来选取元素,包括getElem ...
- 深入理解javascript选择器API系列第二篇——getElementsByClassName
× 目录 [1]使用 [2]classList [3]扩展 前面的话 既然有getElementById()和getElementsByTagName()方法,为什么没有getElementsByCl ...
- 深入理解javascript函数进阶系列第三篇——函数节流和函数防抖
前面的话 javascript中的函数大多数情况下都是由用户主动调用触发的,除非是函数本身的实现不合理,否则一般不会遇到跟性能相关的问题.但在一些少数情况下,函数的触发不是由用户直接控制的.在这些场景 ...
- javascript面向对象系列第三篇——实现继承的3种形式
× 目录 [1]原型继承 [2]伪类继承 [3]组合继承 前面的话 学习如何创建对象是理解面向对象编程的第一步,第二步是理解继承.本文是javascript面向对象系列第三篇——实现继承的3种形式 [ ...
- 深入理解DOM事件类型系列第三篇——变动事件
× 目录 [1]删除节点 [2]插入节点 [3]特性节点[4]文本节点 前面的话 变动(mutation)事件能在DOM中的某一部分发生变化时给出提示,这类事件非常有用,但都只能使用DOM2级事件处理 ...
- 深入理解DOM事件机制系列第三篇——事件对象
× 目录 [1]获取 [2]事件类型 [3]事件目标[4]事件代理[5]事件冒泡[6]事件流[7]默认行为 前面的话 在触发DOM上的某个事件时,会产生一个事件对象event,这个对象中包含着所有与事 ...
- 深入理解脚本化CSS系列第三篇——脚本化CSS类
前面的话 在实际工作中,我们使用javascript操作CSS样式时,如果要改变大量样式,会使用脚本化CSS类的技术,本文将详细介绍脚本化CSS类 style 我们在改变元素的少部分样式时,一般会直接 ...
- 深入理解javascript函数进阶系列第四篇——惰性函数
前面的话 惰性函数表示函数执行的分支只会在函数第一次调用的时候执行,在第一次调用过程中,该函数会被覆盖为另一个按照合适方式执行的函数,这样任何对原函数的调用就不用再经过执行的分支了.本文将详细介绍惰性 ...
随机推荐
- windows下mongodb配置
打开cmd(windows键+r输入cmd)命令行,进入D:\mongodb\bin目录(如图先输入d:进入d盘然后输入cd d:\mongodb\bin), 输入如下的命令启动mongodb服务: ...
- 不该活着的SqlHelper和DBHelper
前言: 还记得刚学ADO.NET的情景么? 还记得当年是怎么从ADO.NET被忽悠到用SqlHelper的么? 话说从入门到走上工作岗位那些年,我们就一直被纯纯地教导或引导,ADO.NET太原始,得封 ...
- Unit Of Work的设计
在DDD开发过程中,一个良好的Uow设计必不可少,我心目中的Uow设计应该具备以下几点: 1.有着良好的抽象,有着恰如其分的命名: 2.能够应付不同的组件,比如你的系统中可能会存在EfUnitOfWo ...
- 全面解析ASP.NET MVC模块化架构方案
什么叫架构?揭开架构神秘的面纱,无非就是:分层+模块化.任意复杂的架构,你也会发现架构师也就做了这两件事. 本文将会全面的介绍我们团队在模块化设计方面取得的经验.之所以加了“全面”二字,是因为本文的内 ...
- 揭秘Windows10 UWP中的httpclient接口[2]
阅读目录: 概述 如何选择 System.Net.Http Windows.Web.Http HTTP的常用功能 修改http头部 设置超时 使用身份验证凭据 使用客户端证书 cookie处理 概述 ...
- 感悟 GNU C 以及将 Vim 打造成 C/C++ 的半自动化 IDE
C 语言在 Linux 系统中的重要性自然是无与伦比.不可替代,所以我写 Linux 江湖系列不可能不提 C 语言.C 语言是我的启蒙语言,感谢 C 语言带领我进入了程序世界.虽然现在不靠它吃饭,但是 ...
- P/Invoke:C#调用C++
P/Invoke的全称是Platform Invoke (平台调用) 它实际上是一种函数调用机制通 过P/Invoke我们就可以调用非托管DLL中的函数. P/Invoke依次执行以下操作: 1. 查 ...
- 《Effective Java》学习笔记——积累和激励
从一个实际案例说起 国庆长假前一个礼拜,老大给我分配了这么一个bug,就是打印出来的报表数量为整数的,有的带小数位,有的不带,毫无规律. 根据短短的两个多月的工作经验以及猜测,最终把范围缩小到以下这段 ...
- 微软MVP攻略 (如何成为MVP?一个SQL Server MVP的经验之谈)
一.本文所涉及的内容(Contents) 本文所涉及的内容(Contents) 初衷 什么是微软MVP? 成为微软MVP的条件? 如何成为微软MVP? (一) 申请时间划分 (二) 前期准备 (三) ...
- 自定义jinja2 过滤器
今天,我们要讲的是自定义jinja2 过滤器这个知识点,因为官方文档对此一代而过,讲得不够清楚,所以我们专门拿出来讲一下. 例子 例子写了两个自定义过滤器,一个是转换字典到字符串的过滤器,一个是返回当 ...