iT邦幫忙

2021 iThome 鐵人賽

DAY 14
3

前情提要

上回說了希望選擇學習火屬性魔法後,艾草帶我走到一棵大樹下。

艾草:「來嘗試用自己現有的魔力試試看能否選取到樹上紅色的果實。」

「呃啊啊啊...呼哈呼哈...魔力呀,聽我號令,供我使喚...(下略一百字」

艾草:「就算把所有中二台詞都說完了,也不會選比較快唷!別急,等選到了來教你怎麼改體內的元素。」

「我我好像感覺到了,體內一股熱氣,從胃部到喉嚨,這難道就是魔力的感覺嗎?」

艾草:「那是你的胃食道逆流啦(・⊝・) ,沒關係,我從頭教導你選取方法吧!」
https://ithelp.ithome.com.tw/upload/images/20210928/20139066M5VscAdu9s.png


DOM

DOM 的英文全名是:Document Object Model ,那它指的是什麼呢?

平常我們在寫 HTML 的時候只會看到一堆程式碼,但網頁是如何解析我們撰寫的這些程式碼呢?

其實是透過 DOM tree 節點樹狀圖的方式,如下:

https://ithelp.ithome.com.tw/upload/images/20210928/20139066XWQsrgmENp.png

DOM tree 是從 document 物件的根節點開始透過樹狀結構的方式,一路解析下來,而我們在操作網頁元素時,可以去選取每個節點,並設定想要的操作,來達成想要的網頁互動效果。

也因為瀏覽器解析 HTML 結構是由上往下解析的關係,所以當你把要載入的 JavaScript 檔案放置於 head 時,卻想操作 body 內的節點時,會無法操作!

因為當瀏覽器一解析到 JavaScript 檔案,會跑去執行 JavaScript 檔案,執行完成後就不再執行了,所以要記得擺放於 body 上方!

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
</head>
<body>

  <!-- JavaScript 檔案載入放置處 -->
  <script src="all.js"></script>
</body>
</html>

DOM 操作方法

選取節點的方式有很多種,這邊來介紹我最常使用到的 querySelector 方式!

querySelector

我們可以使用 querySelector 的方式選取想要的 Element ,而它會回傳符合的第一個節點,querySelector 的選取方式是透過字串的形式,且是使用 CSS 選擇器的方式選取。

HTML:

<h1 id="title" class="title"></h1>

JavaScript:

console.log(document.querySelector('h1'))//<h1 id="title" class="title"></h1>
console.log(document.querySelector('.title'))//<h1 id="title" class="title"></h1>
console.log(document.querySelector('#title')//<h1 id="title" class="title"></h1>

既然說了是透過 CSS 選擇器的方式選取,當然以上三種方法都選的到 h1 Element ,如果想透過後代選擇器方式選取也可以:

HTML:

<ul>
  <li></li>
</ul>

JavaScript:

console.log(document.querySelector('ul li'))//<li></li>

剛剛有提到 querySelector 是選取到第一個節點,那如果我們 Element 想一次選取多個可以怎麼做呢?

可以透過 querySelectorAll 的方式。

querySelectorAll

querySelectorAll 可以選取多個 Element ,並透過 nodeList 的方式回傳給我們,如下:

HTML:

<a href="#">連結一</a>
<a href="#">連結二</a>
<a href="#">連結三</a>

JavaScript:

console.log(document.querySelectorAll('a'))//["<a/>","<a/>","<a/>"]

而該 nodeList 為類陣列物件,為何說是類陣列呢?

因為如果要讀取其中的資料,是必須透過陣列方式去讀取的。

HTML:

<a href="#">連結一</a>
<a href="#">連結二</a>
<a href="#">連結三</a>

JavaScript:

console.log(document.querySelectorAll('a')[0])//<a href="#">連結一</a>

另外 nodeList 也可以使用陣列方法 forEach 唷!

當我們選取到想要的 Element 後想在裡面插入文字內容可以使用什麼方式呢?

textContent

textContent 可以讓你在想要的節點 Node 插入文字 Text,請特別注意插入文字的地方指的是:
https://ithelp.ithome.com.tw/upload/images/20210928/20139066nE51MCzZHy.png

如果我想將某個 h1 Element 內的 Text 從"標題"改成"我是新標題",可以這樣寫:

HTML:

<h1>標題</h1>

JavaScript:

//透過 querySelector 選取 h1 Element 
let el = document.querySelector("h1");

//使用 textContent 替換文字內容
el.textContent = "我是新標題";

更改後的結果,就會顯示我是新標題囉!

但要留意,使用這個方法會將原有的文字內容覆蓋掉。

既然剛剛特別提到 textContent 是插入文字 Text ,那一定也有插入元素 Element 的方法,那就是 innerHTML

innerHTML

可以透過 innerHTML 來插入 element 元素。

例如想在列表元素 ul 內插入 li ,可以這樣操作:

HTML:

<ul class="list">
  <li>我是原本就存在的 li </li>
</ul>

JavaScript:

//透過 querySelector 選取 class list 
let list = document.querySelector(".list");

//使用 innerHTML 插入 Element
list.innerHTML = "<li>我是新增的 li </li>";

顯示後的結果:
https://ithelp.ithome.com.tw/upload/images/20210928/201390661LKfWyc8QU.png

因為 innerHTML 會將原有的內容覆蓋掉,所以會只剩下"我是新增的 li"。

getAttribute

可以透過 getAttribute 來讀取網頁元素的屬性,什麼是屬性呢?

如 a 連結的 href 、 img 的 src 等,每個不同的 HTML 元素內都會有對應的屬性,而我們可以使用 getAttribute 讀取那些屬性。

屬性舉例:

https://ithelp.ithome.com.tw/upload/images/20210928/20139066sgSJOZubjB.png

讀取的方式如下:

HTML:

<a href="#"></a>

JavaScript:

console.log(document.querySelector('a').getAttribute("href"))//#

透過 getAttribute() 這個函式,並將屬性用字串的方式當成參數填進去,就能成功讀取出屬性囉。

setAttribute

我們可以透過 setAttribute() 這個函式來新增或更改屬性的值,它總共需要傳入兩個參數,分別為:

  • 想選取的屬性
  • 想新增、修改的值

而需要透過字串形式的方式,兩個參數間使用, 逗號區隔。

使用方式如下:

HTML:

<a href="#"></a>

JavaScript:

//透過 querySelector 選取 a
const link = document.querySelector("a");

// 透過 setAttribute 更改 href 屬性的值為 "https://www.google.com.tw/"
link.setAttribute("href","https://www.google.com.tw/")

console.log(link)//<a href="https://www.google.com.tw/"></a>

總結

  • 網頁解析 HTML 檔案時會解析成 DOM tree 節點樹狀圖
  • 載入 JavaScript 檔案記得放置於 body
  • querySelector 可以選取第一個符合的 Element
  • querySelectorAll 可以選取多個符合的 Element ,並透過 nodeList 回傳
  • textContent 可以插入文字 Text 內容
  • innerHTML 可以插入 element 元素
  • getAttribute() 可以讀取網頁元素的屬性
  • setAttribute() 可以更改網頁元素的屬性值,可以傳入兩個參數:
    • 想選取的屬性
    • 想新增、修改的值

小練習

請問以下敘述何者錯誤?
A 網頁解析 HTML 時會透過 DOM tree 節點樹狀圖的方式
B querySelectorquerySelectorAll 都可以選取 element 元素,差別在 querySelector 僅能選取第一個符合的
C 如果想讀取元素屬性,可以透過 getAttribute() 、想修改元素屬性,可以透過 setAttribute()
D 透過 innerHTML 插入element 元素時,不會覆蓋原本的element 元素,會透過新增的方式插入element 元素

解答: D 錯誤,使用 innerHTMLtextContent 皆會覆蓋掉原本的內容


參考文獻

JavaScript 必修篇 - 前端修練全攻略(六角學院)


上一篇
入門魔法 - 常用陣列方法(二)find、findIndex
下一篇
入門魔法 - Event 事件
系列文
JavaScript 魔法入門 - 從入門到中階觀念30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言