DOM 選取教學:querySelector 與 getElementById 用法
想要順利的選取到 DOM,首先必須知道父、子層之間的關係。如下:
以 <ul> 的視角來看:
<h2>:兄弟。<section>:父層。<li>:子層。
只要了解元素之間的關係,就可以使用不同的方法來選取目標節點(Node)。
<section>
<h2>Hello JavaScript!</h2>
<ul>
<li>直譯式語言。</li>
<li>變數自動轉型。</li>
<li>弱型別。</li>
</ul>
</section>五種方法速查
| 方法 | 依據 | 回傳 | 找不到時 |
|---|---|---|---|
getElementById() | id | 單一元素 | null |
getElementsByTagName() | 標籤名稱 | HTMLCollection | 空集合 |
getElementsByClassName() | 類別名稱 | HTMLCollection | 空集合 |
querySelector() | CSS 選取器 | 第一個符合的元素 | null |
querySelectorAll() | CSS 選取器 | NodeList | 空集合 |
getElementById(id)
首先,必須確定 HTML 中,元素 id 在指定時必須是唯一的。
參數
id
id 是一個區分大小寫的字串,在 HTML 中是唯一的;只有一個元素應該具有任何給定的 id。
回傳值
指定元素與 id 匹配的 DOM 元素,若匹配不到,則會回傳 null。
注意
id名稱是區分英文大小寫的,因此,必須完全正確才會運作。id名稱須保持唯一性。若有多個相同的id出現,僅會回傳第一個找到的元素。
<header class="header" id="Header">
<h1 class="header__title">專注於網頁設計教學的補習班</h1>
<p class="header__desc">
12 年來協助 2
萬多名學員提昇設計相關技術,成為視覺設計師、網頁設計師與前端工程師。
</p>
</header>console.log(document.getElementById('Header'));getElementsByTagName(name)
搜尋整份 HTML,回傳匹配的指定元素名稱,且有可能是多個。其特性為 HTMLCollection,也有人稱為 類陣列。
小提醒
回傳的對象是個 HTMLCollection(集合),且帶有即時特性,這也代表它能自動更新與 DOM Tree 保持同步。
參數
name
元素的名稱,例如:li、p、div。
回傳值
找到匹配的對象後,會依照 DOM Tree 的順序回傳。若匹配不到,則會回傳 HTMLCollection []。
<footer class="footer">
<div class="container mx-auto footer__cntr">
<h3 class="footer__name">
<a href="javascript:;" target="_blank">圈圈叉叉有限公司</a>
</h3>
<ul class="footer__list">
<li class="footer__item">電話:(02)2882-5252</li>
<li class="footer__item">地址:台北市中正區鄭州路 8 號</li>
<li class="footer__item">信箱:service@ooxx.com.tw</li>
<li class="footer__item">營業時間:下午 2 點 ~ 晚上 10 點</li>
</ul>
</div>
</footer>console.log(document.getElementsByTagName('li'));getElementsByClassName(names)
搜尋整份 HTML,回傳匹配的指定類別名稱,且有可能是多個。其特性為 HTMLCollection,也有人稱為 類陣列。
參數
names
匹配的類別名的字串;多個類別名稱之間以 space 分隔,可以回傳同時具備多個類別名稱的元素。
回傳值
指定元素與類別匹配的 DOM 元素。若匹配不到,則會回傳 HTMLCollection []。
注意
這裡傳入的是 類別名稱,不是 CSS 選取器,所以寫 card 而不是 .card。要用選取器語法請改用 querySelectorAll()。
<section class="card">
<h2 class="card__title">Dreamweaver & CSS網頁設計教學課程</h2>
<img class="card__img" src="./images/dw.png" alt="">
<p class="card__desc">
本課程是基礎的網頁設計入門教學,與 Photoshop
的整合,本課程不是只軟體的操作,更強調設計、網站設計的結構、網頁版面的設計、網頁配色的設計、HTML語法、CSS語法...
</p>
</section>
<section class="card">
<h2 class="card__title">illustrator 平面設計教學與插畫設計課程</h2>
<img class="card__img" src="./images/ai.png" alt="">
<p class="card__desc">
本課程將從最基本的工具操作、平面設計、插畫設計、icon 設計、logo
設計、印刷排版...講起,課程內將有大量的範例讓您實際操作,因此沒有學過
illustrator 的也可以參加喔...
</p>
</section>console.log(document.getElementsByClassName('card'));querySelector(selector)
採用 CSS 選取器的方式進行 DOM 的匹配。
參數
selector
包含一個或多個要匹配的選取器字串。
回傳值
指定 CSS 選取器匹配的第一個 DOM 元素。若匹配不到,則會回傳 null。
<header class="header" id="Header">
<h1 class="header__title">專注於網頁設計教學的補習班</h1>
<p class="header__desc">
12 年來協助 2
萬多名學員提昇設計相關技術,成為視覺設計師、網頁設計師與前端工程師。
</p>
</header>console.log(document.querySelector('#Header'));querySelectorAll(selectors)
採用 CSS 選取器的方式進行 DOM 的匹配。其特性為 NodeList,也有人稱為 類陣列。
參數
selectors
可匹配多個不同類型的 CSS 選取器,CSS 選取器之間用 , 做分隔。
回傳值
指定元素與類別匹配的 DOM 元素。若匹配不到,則會回傳 NodeList []。
<section class="card">
<h2 class="card__title">Dreamweaver & CSS網頁設計教學課程</h2>
<img class="card__img" src="./images/dw.png" alt="">
<p class="card__desc">
本課程是基礎的網頁設計入門教學,與 Photoshop
的整合,本課程不是只軟體的操作,更強調設計、網站設計的結構、網頁版面的設計、網頁配色的設計、HTML語法、CSS語法...
</p>
</section>
<section class="card">
<h2 class="card__title">illustrator 平面設計教學與插畫設計課程</h2>
<img class="card__img" src="./images/ai.png" alt="">
<p class="card__desc">
本課程將從最基本的工具操作、平面設計、插畫設計、icon 設計、logo
設計、印刷排版...講起,課程內將有大量的範例讓您實際操作,因此沒有學過
illustrator 的也可以參加喔...
</p>
</section>console.log(document.querySelectorAll('.card, .card__title'));HTMLCollection 與 NodeList
兩者都是 類陣列:能用索引取值、有 length,但沒有完整的陣列方法。差別在這裡:
| 項目 | HTMLCollection | NodeList |
|---|---|---|
| 由誰回傳 | getElementsBy 系列 | querySelectorAll() |
| 是否即時更新 | 是,DOM 變動會同步 | 否,是當下的快照 |
可否直接 forEach() | 不可 | 可 |
需要用到 map()、filter() 這類陣列方法時,先轉成真正的陣列:
const cards = document.getElementsByClassName('card');
// 方法一:Array.from
Array.from(cards).forEach((card) => console.log(card));
// 方法二:展開運算子
[...cards].forEach((card) => console.log(card));把選取結果存進變數
同一個元素若要用很多次,請先存進變數,別每次都重新查詢整份文件:
const elemBox = document.querySelector('#Box');
elemBox.textContent = '我是內容';
elemBox.classList.add('is-active');常見問題
querySelector 與 getElementById 該用哪一個?
兩者都可以。querySelector() 用 CSS 選取器語法,寫法統一、能表達複雜條件;getElementById() 只認 id、速度略快。實務上多數專案為了一致性會統一用 querySelector()。
HTMLCollection 與 NodeList 有什麼差別?
getElementsBy 系列回傳 HTMLCollection,具即時特性,DOM 變動時內容會自動更新;querySelectorAll() 回傳的 NodeList 是靜態快照,且可以直接使用 forEach()。
選取不到元素時會回傳什麼?
getElementById() 與 querySelector() 回傳 null;getElementsBy 系列回傳空的 HTMLCollection,querySelectorAll() 回傳空的 NodeList。後兩者不是 null,判斷有沒有選到要看 length。
為什麼 getElementsByClassName 不用加點?
因為它的參數是類別名稱本身,不是 CSS 選取器,寫 card 即可。只有 querySelector() 與 querySelectorAll() 才需要寫成 .card 這種選取器語法。
同一個元素會重複選取很多次,該怎麼處理?
把選取結果先存到變數裡再重複使用。每次呼叫選取方法都要重新查詢整份文件,存進變數後直接從記憶體取用,程式也更好讀。