选择器是Css
非常强大的功能,早先一般是通过getElementById
和getElementsByTagName
来获取页面元素,在一些场景下就很不方便。
后来DOM扩展出了Selector API
标准,其中 Selector API Level 1
包含了querySelector
和querySelectorAll
两个方法,可以通过Css选择器匹配页面元素。
一、querySelector查询单个元素
querySelector
用于查询页面中第一个符合规则的元素,可以在Document
实例和Element
实例上调用,接收一个选择器字符串参数,如果查找到则返回 HTMLElement
对象,否则返回null
。
语法格式如下:
1 2 3 | Document实例.querySelector(选择器字符串); Element实例.querySelector(选择器字符串); |
1. Document实例调用
Document
实例调用是获取整个页面匹配的元素。
简单示例如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 | // 获取body元素 let body = document.querySelector( "body" ); console.log(body) // 获取id为container的元素,只会获取第一个 let container = document.querySelector( "#container" ); console.log(container) // 获取class中包含btn的元素,只会获取第一个 let btn = document.querySelector( ".btn" ); console.log(btn); // 获取container直接子类class中包含btn的元素,只会获取第一个 let containerBtn = document.querySelector( "#container>.btn" ); console.log(containerBtn); |
2. Element实例调用
Element
实例调用是获取该元素子树内匹配的元素。
简单示例:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | // 获取ID为container的元素 let container = document.querySelector( "#container" ); // 需要检测元素对象是否存在,存在才有 querySelector 方法 if (container) { // 只查找 container 内class包含 btn 的元素。 let containerBtn = container.querySelector( ".btn" ); console.log(containerBtn); } |
理论上来讲,因为Css可以通过选择器获取页面任意的元素,所以Element
实例调用可以直接写成Document
实例的调用方式,只需要修改选择器字符串参数即可。
例如上例就可以直接写成如下方式:
1 | let containerBtn = document.querySelector( "#container .btn" ); |
并且因为少了一个if判断,代码就更加简洁。当然在有些业务场景下,ELement
实例是已经确定的了,那么直接用 ELement
实例 调用就更加方便了。
二、querySelectorAll查询所有元素
querySelectorAll
方法和querySelector
方法类似,只是它是返回所有匹配的元素,类型是NodeList
。
简单示例:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | // 假设页面有两个div类名包含 article // 获取所有类包含 article 的元素 let articleList = document.querySelectorAll( ".article" ); console.log(articleList); console.log(articleList.length); // 控制台输出: // NodeList(2) [div.article, div.article] // 2 |
querySelectorAll
方法返回的是所有元素,在实务中经常需要遍历,遍历可以使用常规的for
遍历、for of
遍历和forEach
遍历。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 | // for of 遍历 for (let item of articleList) { console.log(item); } // for 遍历 for (let i = 0; i < articleList.length; i++) { console.log(articleList[i]); console.log(articleList.item(i)); } // forEach 遍历 articleList.forEach((item, index) => { console.log(item, index); }); |
1、for in遍历的问题
如果使用for in
遍历,则会把原型链上的一些方法也遍历出来,如entries
,forEach
等。
2、快照而非实时的问题
使用querySelectorAll
方法获取的NodeList
是快照,而非实时的数据。
请看下面这个例子:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 | // 使用 querySelectorAll 获取,articleList 是静态的,非实时的 let articleList = document.querySelectorAll( ".article" ); console.log(articleList); console.log(articleList.length); // 2 setTimeout(() => { // 增加一个元素 let div = document.createElement( "div" ); div.className = "article" ; document.body.appendChild(div); console.log(articleList); // 依旧为2 console.log(articleList.length); }, 0); |
最后设置了一个定时器,往页面塞了一个class
为article
的div
元素,但是 articleList
的长度依旧是2。
如果是用getElementsByClassName
获取,那么 articleList
就是实时的数据。
请看如下例子:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 | // 使用 getElementsByClassName 获取,articleList是实时的 let articleList = document.getElementsByClassName( "article" ); console.log(articleList); console.log(articleList.length); setTimeout(() => { // 增加一个元素 let div = document.createElement( "div" ); div.className = "article" ; document.body.appendChild(div); console.log(articleList); // 这里为3 console.log(articleList.length); }, 0); |

三、小结
- 1.
querySelector
和querySelectorAll
根据Css选择器获取页面元素,功能很强大。 - 2.
querySelectorAll
获取的元素是快照,静态的,而非实时的,注意踩坑。