HOWTO · JavaScript
在 JavaScript 中按類獲取子元素
本教學介紹如何在 JavaScript 中,依 class 名稱從指定父元素內取得一個或多個符合條件的後代元素,並說明如何只選取直接子元素。
本頁內容
若要在父元素中選取具有指定 class 的元素,請使用 querySelector() 取得第一個符合項目,或使用 querySelectorAll() 取得所有符合項目。這些搜尋會包含所有符合條件的後代元素,也包括巢狀元素。若只需要直接子元素,請使用 :scope > 選擇器。下方範例也會展示 getElementsByClassName(),以及子元素屬性與依 class 搜尋的差異。
在 JavaScript 中依 class 取得子元素
請依所需的結果選擇 API:querySelector() 會回傳一個元素或 null;querySelectorAll() 會回傳靜態 NodeList;getElementsByClassName() 則會回傳即時 HTMLCollection。document.getElementById() 適合用來尋找父元素,而 firstElementChild、lastElementChild 和 children 可存取元素子節點,但不會依 class 篩選。除非選擇器明確限制為直接子元素,否則本文介紹的父元素範圍搜尋都可能包含巢狀後代元素。
在 JavaScript 中使用 querySelector() 依 class 名稱取得子元素
在父元素上使用以句點開頭的 CSS class 選擇器。下方獨立的 JavaScript 範例會篩選物件陣列,檢查每個物件的 classes 陣列是否包含 item 這個 token;它不會查詢 DOM。接下來的瀏覽器範例中,父元素或搜尋結果都可能是 null,因此在讀取屬性前,請先確認兩者都存在。
若要快速查看如何在多個元素中比對 class token,請執行這個 JavaScript 範例:
本節中的程式碼以及顯示的標籤或輸出仍為英文。
const elements = [
{ text: 'One', classes: ['item', 'featured'] },
{ text: 'Two', classes: ['item'] },
{ text: 'Note', classes: ['note'] }
];
const matches = elements.filter(element => element.classes.includes('item'));
console.log(matches.map(element => element.text).join(', '));
One, Two
這個獨立的瀏覽器頁面示範如何選取第一個符合項目、所有符合項目、元素子節點屬性、依 class 名稱搜尋,以及使用直接子元素選擇器。這是瀏覽器範例;提供的執行環境快照沒有執行此範例。
<!doctype html>
<html lang="en">
<body>
<ul id="parent">
<li class="item featured">One</li>
<li class="item">Two</li>
<li class="item"><span class="item">Nested three</span></li>
</ul>
<script>
const parent = document.getElementById('parent');
const first = parent?.querySelector('.item');
console.log(first?.textContent); // One
const matches = parent?.querySelectorAll('.item') ?? [];
const lastItem = matches.length ? matches[matches.length - 1] : null;
console.log(lastItem?.textContent.trim() ?? 'No matching item'); // Nested three
console.log([...matches].map(element => element.textContent.trim()));
const firstElement = parent?.firstElementChild;
const lastElement = parent?.lastElementChild;
const childElements = parent?.children;
console.log(firstElement?.textContent.trim(), lastElement?.textContent.trim());
console.log(childElements?.length); // 3 direct element children
const classMatches = parent?.getElementsByClassName('item');
console.log(classMatches?.length); // 4 matching descendants
const directMatches = parent?.querySelectorAll(':scope > .item') ?? [];
console.log(directMatches.length); // 3 direct matches
</script>
</body>
</html>
選擇器 .item 會比對帶有該 class token 的元素,即使元素同時還有其他 class 也一樣。querySelector() 一律只會依文件順序回傳第一個符合的後代元素;它本身不會取得任意最後一個符合項目。在瀏覽器範例中,querySelectorAll('.item') 會收集符合項目,接著透過長度檢查,在有項目時選取最後一個。依提供的標記結構,最後一個符合項目是包含「Nested three.」的巢狀 span。若沒有符合項目,防護式運算式會讓 lastItem 保持為 null,並記錄 No matching item。若要同時要求兩個 class token,請使用 .item.featured 這類不含空格的選擇器。在 CSS 選擇器中,空格表示後代關係,不代表「任一 class」。
在 JavaScript 中使用 querySelectorAll() 方法取得所有具有相同 class 的子節點
呼叫 parent.querySelectorAll('.item') 可取得所有符合該 class 選擇器的後代元素,接著逐一處理回傳的 NodeList。範例中的巢狀 span 也會包含在結果中,因為它同樣帶有 item。若只要符合直接子元素,請使用最後一節介紹的 :scope 方法。
querySelectorAll() 回傳的 NodeList 是靜態集合:它記錄呼叫當下的符合項目,之後 DOM 改變時不會更新。再次呼叫此方法即可取得最新集合。選擇器語法無效時會拋出 SyntaxError DOMException;它不會回傳像 SYNTAX_ERR 這樣的字串。請確認選擇器文字符合 CSS 語法,尤其是從含有標點符號的 class 名稱組合選擇器時。
在 JavaScript 中將 document.getElementById() 與子節點屬性搭配使用
document.getElementById('parent') 會依唯一的 id 找到父元素;它不會搜尋具有特定 class 的子元素。取得父元素後,firstElementChild 和 lastElementChild 會分別回傳它的第一個和最後一個元素子節點。children 則提供其直接元素子節點集合。這些屬性不會依 class 篩選,也會排除 HTML 標籤之間的空白等文字節點。若要依位置存取子元素,或取得所有直接元素子節點,這些屬性就很實用;若要依 class 篩選,請使用選擇器或 class 名稱方法。
在 JavaScript 中使用 getElementsByClassName() 方法依 class 名稱取得一個或多個子元素
呼叫 parent.getElementsByClassName('item'),傳入 class 名稱且不加開頭的句點。它會回傳所有符合的後代元素,包括巢狀元素。若要同時要求多個 class token,請用空格分隔傳入,例如 getElementsByClassName('item featured');元素必須具有列出的每個 class。此 API 會回傳即時 HTMLCollection,因此其長度和成員會隨符合條件的 DOM 變更而更新。若要在變更 DOM 時使用固定快照,請先用 Array.from(...) 複製集合,再逐一處理。
在 JavaScript 中使用 :scope 取得直接子元素
在選擇器前加上 :scope >,即可只比對父元素的直接子元素。例如,parent.querySelectorAll(':scope > .item') 不會包含巢狀的 span.item,而 parent.querySelectorAll('.item') 則會包含它。> 組合子表示直接子元素關係;若省略它,class 選擇器也會搜尋更深層的後代元素。當「子元素」指的是緊鄰父元素的元素,而不是巢狀在父元素內任意深度的元素時,這項差異就是關鍵。