W3Cschool
恭喜您成為首批注冊用戶
獲得88經(jīng)驗值獎勵
當(dāng)元素彼此靠得近時,DOM 導(dǎo)航屬性(navigation property)非常有用。如果不是,那該怎么辦?如何去獲取頁面上的任意元素?
還有其他搜索方法。
如果一個元素有 id
特性(attribute),那我們就可以使用 document.getElementById(id)
方法獲取該元素,無論它在哪里。
例如:
<div id="elem">
<div id="elem-content">Element</div>
</div>
<script>
// 獲取該元素
let elem = document.getElementById('elem');
// 將該元素背景改為紅色
elem.style.background = 'red';
</script>
此外,還有一個通過 id
命名的全局變量,它引用了元素:
<div id="elem">
<div id="elem-content">Element</div>
</div>
<script>
// elem 是對帶有 id="elem" 的 DOM 元素的引用
elem.style.background = 'red';
// id="elem-content" 內(nèi)有連字符,所以它不能成為一個變量
// ...但是我們可以通過使用方括號 window['elem-content'] 來訪問它
</script>
……除非我們聲明一個具有相同名稱的 JavaScript 變量,否則它具有優(yōu)先權(quán):
<div id="elem"></div>
<script>
let elem = 5; // 現(xiàn)在 elem 是 5,而不是對 <div id="elem"> 的引用
alert(elem); // 5
</script>
請不要使用以 id 命名的全局變量來訪問元素
在規(guī)范中 對此行為進(jìn)行了描述,所以它是一種標(biāo)準(zhǔn)。但這是注意考慮到兼容性才支持的。
瀏覽器嘗試通過混合 JavaScript 和 DOM 的命名空間來幫助我們。對于內(nèi)聯(lián)到 HTML 中的簡單腳本來說,這還行,但是通常來說,這不是一件好事。因為這可能會造成命名沖突。另外,當(dāng)人們閱讀 JavaScript 代碼且看不到對應(yīng)的 HTML 時,變量的來源就會不明顯。
在本教程中,我們只會在元素來源非常明顯時,為了簡潔起見,才會使用
id
直接引用對應(yīng)的元素。
在實際開發(fā)中,
document.getElementById
是首選方法。
?
id
? 必須是唯一的
id
必須是唯一的。在文檔中,只能有一個元素帶有給定的id
。
如果有多個元素都帶有同一個
id
,那么使用它的方法的行為是不可預(yù)測的,例如document.getElementById
可能會隨機(jī)返回其中一個元素。因此,請遵守規(guī)則,保持id
的唯一性。
只有 ?
document.getElementById
?,沒有 ?anyElem.getElementById
?
getElementById
方法只能被在document
對象上調(diào)用。它會在整個文檔中查找給定的id
。
到目前為止,最通用的方法是 elem.querySelectorAll(css)
,它返回 elem
中與給定 CSS 選擇器匹配的所有元素。
在這里,我們查找所有為最后一個子元素的 <li>
元素:
<ul>
<li>The</li>
<li>test</li>
</ul>
<ul>
<li>has</li>
<li>passed</li>
</ul>
<script>
let elements = document.querySelectorAll('ul > li:last-child');
for (let elem of elements) {
alert(elem.innerHTML); // "test", "passed"
}
</script>
這個方法確實功能強(qiáng)大,因為可以使用任何 CSS 選擇器。
也可以使用偽類
CSS 選擇器的偽類,例如
:hover
和:active
也都是被支持的。例如,document.querySelectorAll(':hover')
將會返回鼠標(biāo)指針正處于其上方的元素的集合(按嵌套順序:從最外層<html>
到嵌套最多的元素)。
elem.querySelector(css)
調(diào)用會返回給定 CSS 選擇器的第一個元素。
換句話說,結(jié)果與 elem.querySelectorAll(css)[0]
相同,但是后者會查找 所有 元素,并從中選取一個,而 elem.querySelector
只會查找一個。因此它在速度上更快,并且寫起來更短。
之前的方法是搜索 DOM。
elem.matches(css) 不會查找任何內(nèi)容,它只會檢查 elem
是否與給定的 CSS 選擇器匹配。它返回 true
或 false
。
當(dāng)我們遍歷元素(例如數(shù)組或其他內(nèi)容)并試圖過濾那些我們感興趣的元素時,這個方法會很有用。
例如:
<a rel="external nofollow" target="_blank" >...</a>
<a rel="external nofollow" target="_blank" >...</a>
<script>
// 不一定是 document.body.children,還可以是任何集合
for (let elem of document.body.children) {
if (elem.matches('a[href$="zip"]')) {
alert("The archive reference: " + elem.href );
}
}
</script>
元素的祖先(ancestor)是:父級,父級的父級,它的父級等。祖先們一起組成了從元素到頂端的父級鏈。
elem.closest(css)
方法會查找與 CSS 選擇器匹配的最近的祖先。elem
自己也會被搜索。
換句話說,方法 closest
在元素中得到了提升,并檢查每個父級。如果它與選擇器匹配,則停止搜索并返回該祖先。
例如:
<h1>Contents</h1>
<div class="contents">
<ul class="book">
<li class="chapter">Chapter 1</li>
<li class="chapter">Chapter 2</li>
</ul>
</div>
<script>
let chapter = document.querySelector('.chapter'); // LI
alert(chapter.closest('.book')); // UL
alert(chapter.closest('.contents')); // DIV
alert(chapter.closest('h1')); // null(因為 h1 不是祖先)
</script>
還有其他通過標(biāo)簽,類等查找節(jié)點的方法。
如今,它們大多已經(jīng)成為了歷史,因為 querySelector
功能更強(qiáng)大,寫起來更短。
因此,這里我們介紹它們只是為了完整起見,而你仍然可以在舊腳本中找到這些方法。
elem.getElementsByTagName(tag)
? 查找具有給定標(biāo)簽的元素,并返回它們的集合。?tag
? 參數(shù)也可以是對于“任何標(biāo)簽”的星號 ?"*"
?。elem.getElementsByClassName(className)
? 返回具有給定CSS類的元素。document.getElementsByName(name)
? 返回在文檔范圍內(nèi)具有給定 ?name
? 特性的元素。很少使用。例如:
// 獲取文檔中的所有 div
let divs = document.getElementsByTagName('div');
讓我們查找 table 中的所有 input
標(biāo)簽:
<table id="table">
<tr>
<td>Your age:</td>
<td>
<label>
<input type="radio" name="age" value="young" checked> less than 18
</label>
<label>
<input type="radio" name="age" value="mature"> from 18 to 50
</label>
<label>
<input type="radio" name="age" value="senior"> more than 60
</label>
</td>
</tr>
</table>
<script>
let inputs = table.getElementsByTagName('input');
for (let input of inputs) {
alert( input.value + ': ' + input.checked );
}
</script>
不要忘記字母 ?
"s"
?!新手開發(fā)者有時會忘記字符
"s"
。也就是說,他們會調(diào)用getElementByTagName
而不是getElementsByTagName
。
getElementById
中沒有字母"s"
,是因為它只返回單個元素。但是getElementsByTagName
返回的是元素的集合,所以里面有"s"
。
它返回的是一個集合,不是一個元素!
新手的另一個普遍的錯誤是寫:
// 行不通 document.getElementsByTagName('input').value = 5;
這是行不通的,因為它需要的是一個 input 的 集合,并將值賦(assign)給它,而不是賦值給其中的一個元素。
我們應(yīng)該遍歷集合或通過對應(yīng)的索引來獲取元素,然后賦值,如下所示:
// 應(yīng)該可以運行(如果有 input) document.getElementsByTagName('input')[0].value = 5;
查找 .article
元素:
<form name="my-form">
<div class="article">Article</div>
<div class="long article">Long article</div>
</form>
<script>
// 按 name 特性查找
let form = document.getElementsByName('my-form')[0];
// 在 form 中按 class 查找
let articles = form.getElementsByClassName('article');
alert(articles.length); // 2, found two elements with class "article"
</script>
所有的 "getElementsBy*"
方法都會返回一個 實時的(live) 集合。這樣的集合始終反映的是文檔的當(dāng)前狀態(tài),并且在文檔發(fā)生更改時會“自動更新”。
在下面的例子中,有兩個腳本。
<div>
? 的集合的引用。截至目前,它的長度是 ?1
?。<div>
? 時運行,所以它的長度是 ?2
?。<div>First div</div>
<script>
let divs = document.getElementsByTagName('div');
alert(divs.length); // 1
</script>
<div>Second div</div>
<script>
alert(divs.length); // 2
</script>
相反,querySelectorAll
返回的是一個 靜態(tài)的 集合。就像元素的固定數(shù)組。
如果我們使用它,那么兩個腳本都會輸出 1
:
<div>First div</div>
<script>
let divs = document.querySelectorAll('div');
alert(divs.length); // 1
</script>
<div>Second div</div>
<script>
alert(divs.length); // 1
</script>
現(xiàn)在我們可以很容易地看到不同之處。在文檔中出現(xiàn)新的 div
后,靜態(tài)集合并沒有增加。
有 6 種主要的方法,可以在 DOM 中搜索元素節(jié)點:
方法名 | 搜索方式 | 可以在元素上調(diào)用? | 實時的? |
querySelector
|
CSS-selector | ? | - |
querySelectorAll
|
CSS-selector | ? | - |
getElementById
|
id
|
- | - |
getElementsByName
|
name
|
- | ? |
getElementsByTagName
|
tag or '*'
|
? | ? |
getElementsByClassName
|
class | ? | ? |
目前為止,最常用的是 querySelector
和 querySelectorAll
,但是 getElement(s)By*
可能會偶爾有用,或者可以在舊腳本中找到。
此外:
elem.matches(css)
? 用于檢查 ?elem
? 與給定的 CSS 選擇器是否匹配。elem.closest(css)
? 用于查找與給定 CSS 選擇器相匹配的最近的祖先。?elem
? 本身也會被檢查。讓我們在這里提一下另一種用來檢查子級與父級之間關(guān)系的方法,因為它有時很有用:
elemB
? 在 ?elemA
? 內(nèi)(?elemA
? 的后代)或者 ?elemA==elemB
?,?elemA.contains(elemB)
? 將返回 true。這是帶有表格(table)和表單(form)的文檔。
如何查找?……
id="age-table"
? 的表格。label
? 元素(應(yīng)該有三個)。td
?(帶有 “Age” 字段)。name="search"
? 的 ?form
?。input
?。input
?。在一個單獨的窗口中打開 table.html 頁面,并對此頁面使用瀏覽器開發(fā)者工具。
實現(xiàn)的方式有很多種。
以下列舉的是其中一些方法:
// 1. 帶有 id="age-table" 的表格。
let table = document.getElementById('age-table')
// 2. 表格內(nèi)的所有 label 元素
table.getElementsByTagName('label')
// 或
document.querySelectorAll('#age-table label')
// 3. 表格中的第一個 td(帶有 "Age" 字段)
table.rows[0].cells[0]
// 或
table.getElementsByTagName('td')[0]
// 或
table.querySelector('td')
// 4. 帶有 name="search" 的 form。
// 假設(shè)文檔中只有一個 name="search" 的元素
let form = document.getElementsByName('search')[0]
// 或者,專門對于 form
document.querySelector('form[name="search"]')
// 5. 表單中的第一個 input
form.getElementsByTagName('input')[0]
// 或
form.querySelector('input')
// 6. 表單中的最后一個 input
let inputs = form.querySelectorAll('input') // 查找所有 input
inputs[inputs.length-1] // 取出最后一個
Copyright©2021 w3cschool編程獅|閩ICP備15016281號-3|閩公網(wǎng)安備35020302033924號
違法和不良信息舉報電話:173-0602-2364|舉報郵箱:jubao@eeedong.com
掃描二維碼
下載編程獅App
編程獅公眾號
聯(lián)系方式:
更多建議: