Vanilla JavaScript | Get DOM Elements (get anchor and image with querySelector)

2021-08-09

筆記 JS 如何使用 JS 原生語法取得 DOM 元素,包含介紹 GetElementById, GetElementByName, QuerySelector, QuerySeletorAll ,並且介紹如何應用這些語法,提供將網頁上所有的 Anchor Link 擷取的解決方案 😎

JavaScript logo

說明

Template.html 是本次要練習 get element 的 DOM,此外 Template.html 有發佈於 GitHub 可以連結後使用 DevTools 進行實際操作。

實驗所使用的 Scripts GitHub Repo

Template.html

<body>
  <p id="p1">Lorem ipsum dolor sit amet consectetur adipisicing elit.
    <a id="a1" href="https://www.domain.local/Posts/Article?title=js">Link1</a>
  </p>
  <p>Earum atque distinctio itaque mollitia perspiciatis fuga vel voluptate molestias.
    <a id="a2" name="link" href="#link2">Link2</a>
    <a href="#link3">Link3</a>
  </p>
  <div class="footer">
    <p>Rerum vero dolore soluta culpa praesentium, mollitia voluptates?
      <a class="btn" name="link" href="#link4">Link4</a>
    </p>
    <a class="btn" id="a5" name="link" href="#link5">Link5</a>
  </div>
</body>

getElementById()

基本招式利用 element 的 Id 來指向 element,要注意的是如果 DOM 有重複的 Id,只會取到第一個相符 Id 的 element。

const tag = document.getElementById('a1');

tag 的型別為 HTMLAnchorElement

具有的 Properties 如表格的示範(以 #a1 tag 為例)

<a id="a1" href="https://www.domain.local/Posts/Article?title=js">Link1</a>
Property Example Inherit
innerHtml Link1 element.innerHTML
innerText Link1 HTMLElement.innerText
text Link1 Node.textContent
href https://www.domain.local/Posts/Article?title=js HTMLAnchorElement
hostname www.domain.local HTMLAnchorElement
pathname /Posts/Article HTMLAnchorElement
search ?title=js HTMLAnchorElement

確認實際型別的方法

Object.prototype.toString.call(variable)

getElementsByClassName()

這個方法是以元素的 Class Name 搜尋元素。

<div class="footer">
  <p>Rerum vero dolore soluta culpa praesentium, mollitia voluptates?
    <a class="btn" name="link" href="#link4">Link4</a>
  </p>
  <a class="btn" id="a5" name="link" href="#link5">Link5</a>
</div>
const htmlCollections = document.getElementsByClassName('btn');

htmlCollections.namedItem('a4')
// null

const tag_a_a5 = htmlCollections.namedItem('a5');
// link5

getElementsByTagName()

這個方法是以元素的 Tag Name 搜尋元素。

getElementsByClassName 及 getElementsByTagName 所回傳的都是 array-like 的 HtmlCollections Type,其只有 item* 及 namedItem Method,如果想要 loop 它的 elements 可以利用 Array.from 來處理。

使用 item Method 的差異在於使用索引子 (htmlCollections[0]) 的方式超過陣列範圍可能會發生 undefined,使用 item 不存在的 key 則會回報 null。

const htmlCollections = document.getElementsByTagName('a');

htmlCollections.length
// 5

htmlCollections.item(0)

Array.from(htmlCollections).forEach(item => {
    console.log(item);
});

QuerySelector()

QuerySelector 以及 QuerySelectorAll 支援 jQuery Selector like 的方式,也就是以 CSS Selector 的方式去指向 element,方便性遠勝原本只能使用 getElementByClassName 😏

const tag_a_link4 = document.querySelector('.btn')
// link4

QuerySeletorAll()

QuerySeletorAll 與 getElementsByClassName 及 getElementsByTagName 的差別在於回傳的型別為 NodeList,NodeList 相較於 HtmlCollections 提供了更多的 Method,例如 values 以及 entries。

const nodeList_btn = document.querySelectorAll('.btn')
// nodelist: a.btn, a#a5.btn

const nodeList_name_link = document.querySelectorAll('[name="link"]')
// nodelist: a#a2, a.btn, a#a5.btn

nodeList_btn.item(0)

for(let value of nodeList_btn.values()) {
    console.log(value);
}

for(let entry of nodeList_btn.entries()) {
    console.log(entry);
}

應用情境

取得網頁上所有的連結

const res = [];
document.querySelectorAll('a').forEach(
  aTag => res.unshift([aTag.text, aTag.href])
);
copy(res)

取得所有連結並轉換為 Json Format

let linkList = [];
document.querySelectorAll('a').forEach(a => {
    let href = a.getAttribute('href') || '';
    let text = a.innerText.trim() || '[No Text]';
    let className = a.getAttribute('class') || '';
    
    href = decodeURIComponent(href);    
    linkList.push(`{"text": "${text}", "href": "${href}", "class": "${className}"}`);
});

copy('[' + linkList.join(',\n' ) + ']');
const newWindow = window.open('', '_blank');
newWindow.document.write('[' + linkList.join(',<br/>' ) + ']');

取得所有圖片並轉換為 Json Format

let imgList = [];
document.querySelectorAll('img').forEach(img => {
    let src = img.getAttribute('src') || '[No src]';
    let alt = img.getAttribute('alt') || '[No alt]';
    
    src = decodeURIComponent(src);
    imgList.push(`{"src": "${src}", "alt": "${alt}"}`);
});

copy('[' + imgList.join(',\n') + ']');
const newWindow = window.open('', '_blank');
newWindow.document.write('[' + imgList.join(',<br/>') + ']');

參考資料

Dcoument | MDN