隨時隨地閱讀更多技術實戰乾貨,獲取項目源碼、學習資料,請關注源代碼社區公衆號(ydmsq666)、博主微信(guyun297890152)、QQ技術交流羣(183198395)。
一、介紹
先看看以前查找元素的js方法
儘管DOM作爲API已經非常完善了,但是爲了實現更多的功能,DOM仍然進行了擴展,其中一個重要的擴展就是對選擇器API的擴展。有了新的 Selectors API後,可以用更精確的方式來指定希望獲取的元素,而不必用標準的DOM方式去遍歷。 Selectors API與現在CSS選擇規則一樣,通過它可以查找一個或者多個元素。新的查詢方法有:
querySelectorAll()、querySelector()和matchesSelector()
通過CSS選擇符查詢DOM文檔取得元素引用的功能變成了原生的API,解析和樹查詢操作在瀏覽器內部通過編譯後的代碼來完成,極大地改善了性能。
還可以爲 Selectors API函數同時指定多個選擇規則,如
//選擇文檔中類名爲oneClass或者twoClass的第一個元素
var x=document.querySelector(".oneClass","twoClass");
而對於querySelectorAll()來說,滿足規則的任何一個元素都會被返回,多條規則用逗號分隔。下面看示例
二、示例
1、querySelector()
querySelector()方法接收一個CSS選擇符,返回與該模式匹配的第一個元素,如果沒有找到匹配的元素,返回null。該方法既可用於文檔document類型,也可用於元素element類型。
[注意]IE7-瀏覽器不支持
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>測試Selectors API</title>
</head>
<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>
</html>
頁面結果如下
2、querySelectorAll()
querySelectorAll()接收一個CSS選擇符,返回一個類數組對象NodeList的實例。具體來說,返回的值實際上是帶有所有屬性和方法的NodeList,而其底層實現則類似於一組元素的快照,而非不斷對文檔進行搜索的動態查詢。這樣實現可以避免使用NodeList對象通常會引起的大多數性能問題。只要傳給querySelectorAll()方法的CSS選擇符有效,該方法都會返回一個NodeList對象,而不管找到多少匹配的元素。沒有匹配元素時,返回空的類數組對象,而不是null
[注意]IE7-瀏覽器不支持
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>測試Selectors API</title>
</head>
<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>
</html>
運行結果如下:
3、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()方法。所以兼容寫法爲:
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>測試Selectors API</title>
</head>
<body id="test">
<script>
console.log(matchesSelector(document.body, '#test'));//true
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);
}
}
</script>
</body>
</html>
三、優劣對比
1、非實時
新增方法雖然方便了許多但是也有些缺陷,與getElementById()和getElementsByTagName()方法不同,querySelector()和querySelectorAll()方法得到的類數組對象是非動態實時的
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>測試Selectors API</title>
</head>
<body id="test">
<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>
</body>
</html>
2、參數缺陷
selector類方法在元素上調用時,指定的選擇器仍然在整個文檔中進行匹配,然後過濾出結果集,以便它只包含指定元素的後代元素。這看起來是違反常規的,因爲它意味着選擇器字符串能包含元素的祖先而不僅僅是所匹配的元素
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>測試Selectors API</title>
</head>
<body id="test">
<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>
</body>
</html>
按照正常理解,控制檯應該返回空的類數組對象,因爲id爲container的div元素的子元素中,不存在div元素嵌套的情況
但是,該方法實際返回[div div]。這是因爲參數中的選擇器包含了元素的祖先
所以,如果出現後代選擇器,爲了防止該問題,可以在參數中顯式地添加當前元素的選擇器
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>測試Selectors API</title>
</head>
<body id="test">
<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>
</body>
</html>
雖然存在着非實時和參數缺陷的問題,但是瑕不掩瑜,selector類方法的出現極大地簡化了查找元素的繁瑣操作。而且,它們支持IE8瀏覽器
參考鏈接:https://www.cnblogs.com/xiaohuochai/p/5798014.html