實際前端開發(fā)工作中泌参,我們經(jīng)常會遇到要獲取某些元素霎桅,以達到更新該元素的樣式旅择、內(nèi)容等目的宣赔。而文檔對象模型 (DOM) 是HTML和XML文檔的編程接口预麸,它提供了對文檔的結(jié)構(gòu)化的表述,并定義了一種方式可以從程序中對該結(jié)構(gòu)進行訪問儒将,從而改變文檔的結(jié)構(gòu)吏祸,樣式和內(nèi)容。DOM 將文檔解析為一個由節(jié)點和對象(包含屬性和方法的對象)組成的結(jié)構(gòu)集合钩蚊,它會將web頁面和腳本或程序語言連接起來贡翘。也因此蹈矮,JavaScript可以通過DOM API獲取元素節(jié)點,方法有如下幾種:其中querySelector()
和querySelectorAll()
為ES5的元素選擇方法
1床估、getElementById():
接收一個參數(shù):要取得的元素的ID(區(qū)分大小寫含滴,必須嚴格匹配)诱渤,返回一個Element對象(也可看作是動態(tài)NodeList集合丐巫,只是集合中只包含一個匹配的元素,但也會實時反映DOM節(jié)點的變化)勺美,若當前文檔中擁有特定ID的元素不存在則返回nul递胧。
語法:
element = document.getElementById(id);
示例:刪除
<body>
<div id="myDiv">
<p class="myP">hello world</p>
<p class="myP">hello dolby</p>
<p class="myP">hello dot</p>
<p class="myP">hello bean</p>
</div>
<script>
var div = document.getElementById("myDiv");
console.log(div); //(1)
var body=document.querySelector('body');
body.removeChild(div);
console.log(body); //(2)
</script>
</body>
//(1)處打印值
<div id="myDiv">
<p class="myP">hello world</p>
<p class="myP">hello dolby</p>
<p class="myP">hello dot</p>
<p class="myP">hello bean</p>
</div>
//(2)處打印值
<body>
<script>
var div = document.getElementById("myDiv");
console.log(div); //(1)
var body=document.querySelector('body');
body.removeChild(div);
console.log(body); //(2)
</script>
</body>
示例:
<!DOCTYPE html>
<html>
<head>
<title>getElementById example</title>
<script>
function changeColor(newColor) {
var elem = document.getElementById("para1");
elem.style.color = newColor;
}
</script>
</head>
<body>
<p id="para1">Some text here</p>
<button onclick="changeColor('blue');">blue</button>
<button onclick="changeColor('red');">red</button>
</body>
</html>
getElementById()方法不會搜索不在文檔中的元素。當創(chuàng)建一個元素且分配ID后赡茸,必須要使用insertBefore()或其他類似的方法把元素插入到文檔中之后才能使用 getElementById() 獲取到:
var element = document.createElement("div");
element.id = 'testqq';
var el = document.getElementById('testqq'); // el will be null!
2缎脾、getElementsByClassName():
接收一個參數(shù),即包含一個或多個類名的字符串(類名通過空格分隔)占卧,返回一個HTMLCollection動態(tài)集合(也可以說返回一個NodeList類數(shù)組對象),集合中包含以當前元素為根節(jié)點,所有指定 class 名的子元素恰画。
語法:
var elements = document.getElementsByClassName(names);
var elements = rootElement.getElementsByClassName(names);
getElementsByClassName 可以在任意的元素上調(diào)用看彼,不僅僅是document。 調(diào)用這個方法的元素將作為本次查找的根元素叭喜。
示例:
- 獲取所有 class 為 'test' 的元素:
document.getElementsByClassName('test');
- 獲取所有 class 同時包括 'red' 和 'test' 的元素:
document.getElementsByClassName('red test');
- 在id 為'main'的元素的子節(jié)點中贺拣,獲取所有class為'test'的元素:
document.getElementById('main').getElementsByClassName('test');
示例:刪除
//html代碼
<div class="myDiv">
<p class="myP">hello world</p>
<p class="myP">hello dolby</p>
<p class="myP">hello dot</p>
<p class="myP">hello bean</p>
</div>
//js代碼一
<script>
var div = document.getElementsByClassName("myDiv");
console.log(div); //(3)
var p = document.getElementsByClassName("myP");
for (var i = 0; i < p.length; i++) {
div[0].removeChild(p[i]);
}
console.log(p); //(4)
</script>
//(3)處打印值
[div.myDiv] //一個動態(tài)的HTMLCollection集合,長度為1捂蕴,innerHTML為<p class="myP">hello dolby</p>譬涡,<p class="myP">hello bean</p>,為什么沒有其他兩個p元素一會兒解釋啥辨。
//(4)處打印值
[p.myP,p.myP] //一個動態(tài)的HTMLCollection集合涡匀,長度為2,innerHTML分別為"hello dolby"溉知,"hello bean"陨瘩。
以上用刪除節(jié)點的方法驗證了getElementsByClassName方法返回的是一個HTMLCollection動態(tài)集合。
??以上代碼中着倾,首先div取得了頁面中類名為"myDiv"的元素組成的動態(tài)集合拾酝,p取得了頁面中類名為"myP"的元素組成的動態(tài)集合,接著用一個for循環(huán)來刪除"myDiv"集合中第一項(即上例中唯一的div元素)中的"myP"集合中的每一項卡者,結(jié)果只有第一項和第三項被刪除了蒿囤,這是為什么呢?
原因是動態(tài)集合中DOM結(jié)構(gòu)的變化能夠自動反映到所保存的對象中崇决,最開始p.legth=4材诽,當i=0時刪除了頁面中第一個p元素底挫,此后p.length=3;i=1時刪除了剩余的三個p中的項目索引為1的項脸侥,此后p.length=2建邓;i=2時已不滿足i<p.length這一條件,所以不會繼續(xù)執(zhí)行循環(huán)睁枕。至此只刪除了頁面上的第一和第三個p元素官边,所以打印p得到了一個長度為2的HTMLCollection動態(tài)集合,其中包含"hello dolby"和"hello bean"外遇,p的變化也實時反映到了動態(tài)集合div中注簿,所以才有(1)處的打印結(jié)果。
那么怎樣才能遍歷類數(shù)組對象HTMLCollection集合中的每一項并且刪除所有項呢跳仿?
還是一個for循環(huán)搞定??诡渴,每次刪除對象集合中的最后一項就可以啦~
//js代碼二
<script>
var div = document.getElementsByClassName("myDiv")[0];
console.log(div); //(5)
var p = document.getElementsByClassName("myP");
for (var i=p.length;i--;){
div.removeChild(p[i]);
}
console.log(p); //(6)
</script>
//(5)處打印值
<div class="myDiv"></div>
//(6)處打印值
[] //空的HTMLCollection集合,長度為0
3菲语、getElementsByTagName():
接收一個參數(shù):要取得的元素的標簽名(不區(qū)分大小寫)妄辩,返回一個HTMLCollection動態(tài)集合(也可以說返回一個NodeList類數(shù)組對象),集合中包含以當前元素為根節(jié)點(不包括當前元素自身),所有指定標簽名的子元素山上,子元素的順序是在當前元素的子樹中出現(xiàn)的順序眼耀,如果沒有搜索到元素則集合為空。
語法:
elements = element.getElementsByTagName(tagName)
示例:
// check the alignment on a number of cells in a table.
var table = document.getElementById("forecast-table");
var cells = table.getElementsByTagName("td");
for (var i = 0; i < cells.length; i++) {
var status = cells[i].getAttribute("data-status");
if ( status == "open" ) {
// grab the data
}
}
示例:刪除
<body>
<div id="myDiv">
<p class="myP">hello world</p>
<p class="myP">hello dolby</p>
<p class="myP">hello dot</p>
<p class="myP">hello bean</p>
</div>
<script>
var div = document.getElementById("myDiv");
console.log(div); //(7)
var p = document.getElementsByTagName("p");
//以下for循環(huán)改為for (var i=0,len=p.length;i<len;i++) {div.removeChild(p[0]);}也可胶哲;將集合p的長度賦值給變量len畔塔,這樣len就是一個固定值,每次都刪除當前集合項目索引為0的項鸯屿,就可以循環(huán)遍歷刪除掉集合里的所有項澈吨。
for (var i=p.length;i--;){
div.removeChild(p[i]);
}
console.log(p); //(8)
</script>
</body>
與getElementByClassName相同,返回動態(tài)集合寄摆,所以循環(huán)刪除結(jié)果也相同
//(7)處打印值
<div id="myDiv"></div>
//(8)處打印值
[] //空的HTMLCollection集合谅辣,長度為0
4、getElementsByName():
接收一個參數(shù):帶有給定name屬性值的元素婶恼,返回一個動態(tài)NodeList類數(shù)組對象桑阶,對象中包含以當前元素為根節(jié)點,所有指定name屬性值的子元素勾邦。最常用的場景是取得單選按鈕蚣录。
示例:
<!DOCTYPE html>
<html lang="en">
<head>
...
</head>
<body>
<form name="up"><input type="text"></form>
<div name="down"><input type="text"></div>
<script>
var up_forms = document.getElementsByName("up");
console.log(up_forms[0].tagName); // returns "FORM"
</script>
</body>
</html>
示例:刪除
<body>
<div id="myDiv">
<input type="radio" name="fav-color">red
<input type="radio" name="fav-color">green
<input type="radio" name="fav-color">blue
</div>
<script>
var div = document.getElementById("myDiv");
console.log(div); //(9)
var ipt_favCol = document.getElementsByName("fav-color");
for (var i = ipt_favCol.length; i--;) {
div.removeChild(ipt_favCol[i]);
}
console.log(ipt_favCol); //(10)
</script>
</body>
getElementByName返回的是一個NodeList動態(tài)集合
//(9)處打印值
<div id="myDiv">
"red"
"green"
"blue"
</div>
//(10)處打印值
[] //空的NodeList集合,長度為0
5眷篇、querySelector():
接收一個參數(shù):一個包含一個或多個CSS 選擇器的字符串(多個選擇器以逗號分隔)萎河,返回匹配指定CSS選擇器的第一個元素節(jié)點(無法選中CSS偽元素),沒有發(fā)現(xiàn)匹配的節(jié)點則返回null。
語法:
element = document.querySelector(selectors);
示例:一個強大的選擇方式
<div class="user-panel main">
<input name="login"/> //這個標簽將被返回
</div>
<script>
var el = document.querySelector("div.user-panel.main input[name=login]");
</script>
示例:如果要匹配的ID或選擇器不符合 CSS 語法(比如不恰當?shù)厥褂昧嗣疤柣蛘呖崭瘢┡氨惚仨氂梅葱备軐⑦@些字符轉(zhuǎn)義玛歌。由于 JavaScript 中,反斜杠是轉(zhuǎn)義字符擎椰,所以當你輸入一個文本串時支子,你必須將它轉(zhuǎn)義兩次(一次是為 JavaScript 字符串轉(zhuǎn)義,另一次是為 querySelector 轉(zhuǎn)義):
<div id="foo\bar"></div>
<div id="foo:bar"></div>
<script>
console.log('#foo\bar') // "#fooar"
document.querySelector('#foo\bar') // 不匹配任何元素
console.log('#foo\\bar') // "#foo\bar"
console.log('#foo\\\\bar') // "#foo\\bar"
document.querySelector('#foo\\\\bar') // 匹配第一個div
document.querySelector('#foo:bar') // 不匹配任何元素
document.querySelector('#foo\\:bar') // 匹配第二個div
</script>
示例:刪除
<div id="myDiv">
<p class="myP">hello world</p>
<p class="myP">hello dolby</p>
<p class="myP">hello dot</p>
<p class="myP">hello bean</p>
</div>
<script>
var div = document.getElementById("myDiv");
console.log(div); //(11)
var p = document.querySelector("p");
div.removeChild(p);
console.log(p); //(12)
</script>
//(11)處打印值
<div id="myDiv">
<p class="myP">hello dolby</p>
<p class="myP">hello dot</p>
<p class="myP">hello bean</p>
</div>
//(12)處打印值
<p class="myP">hello world</p> //如你所見达舒,querySelector也是靜態(tài)的快照
6值朋、querySelectorAll():
接收一個參數(shù):一個包含一個或多個CSS 選擇器的字符串(多個選擇器以逗號分隔),返回靜態(tài)NodeList對象集合休弃,該集合中包含匹配指定CSS選擇器的所有節(jié)點吞歼,元素節(jié)點的變化無法實時反映在結(jié)果中;如果參數(shù)中包含CSS偽元素則返回一個空的對象集合塔猾。
語法:
elementList = document.querySelectorAll(selectors);
示例:
var matches = document.querySelectorAll("div.note, div.alert");
示例:刪除
<div id="myDiv">
<p class="myP">hello world</p>
<p class="myP">hello dolby</p>
<p class="myP">hello dot</p>
<p class="myP">hello bean</p>
</div>
<script>
var div = document.getElementById("myDiv");
console.log(div); //(13)
var p = document.querySelectorAll("p");
for (var i = 0; i < p.length; i++) {
div.removeChild(p[i]);
}
console.log(p); //(14)
</script>
//(13)處打印值
<div id="myDiv"></div>
//(13)處打印值
[p.myP,p.myP,p.myP,p.myP] //返回的是靜態(tài)NodeList集合,元素節(jié)點的變化無法實時反映在結(jié)果中
7稽坤、elementFromPoint():
接收兩個參數(shù):分別是相對于當前窗口左上角的橫縱坐標丈甸,單位為CSS像素,不需要加單位尿褪;返回位于頁面指定位置的元素睦擂,如果該元素不可返回(如滾動條)則返回它的父元素,如果坐標值無意義(如負值)則返回null杖玲。
語法
var element = document.elementFromPoint(x, y);
示例:
<!DOCTYPE html>
<html lang="en">
<head>
<title>elementFromPoint example</title>
<script>
function changeColor(newColor) {
elem = document.elementFromPoint(2, 2);
elem.style.color = newColor;
}
</script>
</head>
<body>
<p id="para1">Some text here</p>
<button onclick="changeColor('blue');">blue</button>
<button onclick="changeColor('red');">red</button>
</body>
</html>
這一個獲取元素的方法用得不多所以不多做介紹顿仇。
是不是覺得看了上面這些頭好大啊,什么是動態(tài)什么是靜態(tài)摆马,有沒有好記一點的方法呢臼闻?
有噠!
你可以簡單地理解為囤采,getElementBy系列返回的都是動態(tài)的HTMLCollection集合述呐,動態(tài)集合中的DOM結(jié)構(gòu)變化能實時地反映到所保存的對象中,而querySelector系列返回的都是靜態(tài)的NodeList對象蕉毯,是一個快照乓搬,對DOM的任何操作都不會對其產(chǎn)生影響。
那么Nodelist和HTMLCollection有什么異同呢代虾?
相同點:
- 二者都是類數(shù)組對象
- 二者都具有l(wèi)ength屬性
- 二者都具有item()方法
- 二者都是動態(tài)的元素集合进肯,每次訪問都需要重新對文檔進行查詢。
你一定會好奇棉磨,誒江掩?前面不是說querySelector系列返回的都是靜態(tài)的NodeList對象咩?怎么又變成動態(tài)的呢?原因在此:
規(guī)范中對 querySelectorAll 有明確要求频敛,規(guī)定其必須返回一個靜態(tài)的 NodeList 對象项郊。
在Chrome中情況如下:
document.querySelectorAll('a').toString(); // return "[object NodeList]"
document.getElementsByTagName('a').toString(); // return "[object HTMLCollection]"
不同點:
- NodeList 對象會包含文檔中的所有節(jié)點,如 Element斟赚、Text 和 Comment 等着降;HTMLCollection 對象只會包含文檔中的 Element 節(jié)點。
參考資料:
- document.getElementById
- document.getElementByIClassName
- document.getElementByITagName
- document.getElementByIName
- document.querySelector
- document.querySelectorAll
- document.elementFromPoint
- 深入理解javascript中的動態(tài)集合——NodeList拗军、HTMLCollection和NamedNodeMap
- 靜態(tài)NodeList 和 動態(tài)NodeList的區(qū)別
- querySelectorAll 方法相比 getElementsBy 系列方法有什么區(qū)別任洞?