DOM — 選取網頁元素

Vicky
宅宅薇琪 [前端學習筆記]
14 min readMar 4, 2021

--

圖片取自維基百科

DOM (Document Object Model,文件物件模型),是一個以樹狀結構來表示 HTML 文件的模型,而組合起來的樹狀圖,我們稱之為「DOM Tree」。我們把 HTML 每個節點的關係攤來看,就好像是一棵樹一樣。

在最根部的地方,就是 document,就是 BOM 圖中 window 下面的那個。往下可以延伸出一個個的 HTML 標籤,一個節點就是一個標籤,往下又可以再延伸出「文本節點」與「屬性的節點」。

為什麼要瞭解 DOM (Document Object Model)?

我們先來看看開發者寫出的程式碼,在瀏覽器裡會變成什麼樣子 ~

開發者、網頁工程師看到的介面 (如下左圖)

瀏覽器解析程式碼成 DOM tree (節點樹狀圖) (如下右圖)

網頁瀏覽器會如何做呈現 ?

網頁是由瀏覽器負責運行,因此可以知道瀏覽器其實就是一種編譯器負責去編譯我們寫的網頁程式。

網頁瀏覽器在解析時,會將程式碼變成 DOM tree (節點樹狀圖)。

  • DOM 全名為 Document Object Model 中文翻譯為「文件物件模型」,但其實就是把一份 HTML 文件內的各個標籤,包括文字、圖片等等都定義成物件,而這些物件最終會形成一個樹狀結構。

了解如何透過 JavaScript 去操控 DOM,就可以輕鬆地去執行網頁裡的節點。

  • 可以把 a 屬性 href 抓出 : 透過 JavaScript 動態去更改 a 標籤內的 href 連結。
  • 可以操控 a 標籤 : 把裡面的文字給換掉。
  • 可以操控 h1 的標籤,希望註冊一個點擊事件。當點擊 h1 標題時,text 就會自動變成 “header 1”,再次點擊 h1 標題時,text 就會自動變成 “header 2”…。

了解 DOM 才真正進入到網頁,可以和使用者做互動。

如何透過網頁找到 Document

網頁瀏覽器在解析時,會先產生出 document,document 裡有 Element 的資料。當需要選取元素時,就可以透過 DOM 功能很友善的選取到內容。

當網頁一打開,就自動產生 document (網頁一打開就解析好了) 。

  • 網頁一解析完網頁內容後,會產生 DOM tree (節點樹狀圖),產生各種節點來方便做讀取。
  • DOM (Document Object Model) 為物件的格式,方便節點做整理,可以使用物件的方式來讀取他。

當在 console 輸入 document,會回傳 “回傳整個文件的文本”,把整個內容都解析出來。

console.log(document);  // 回傳整個文件的文本

點開可以看到 HTML 的內容,可以選取到對應的節點。

DOM 環境配置

<script src="all.js"></script>

以上一段程式碼,可以放在 <head> 裡,或是 <body> 裡。

但是在 DOM 裡,此段 <script src="all.js"></script> 程式碼只能放在 </body> 前面。

  • 網頁瀏覽器一打開,HTML 程式碼會一行一行執行,HTML 標籤由上到下都解析成 DOM 節點,才可以使用 JavaScript 去抓取裡頭的內容。

若把 <script src="all.js"></script> 程式碼放在 <head> 裡,就抓取不到 HTML 的節點。(因為 HTML 標籤節點還沒解析出來)

querySelector 選擇器

該如何透過 JavaScript 程式語法來抓取 DOM 裡的網頁元素 Element。

網頁一打開就會自動產生 DOM,document 是根節點,在此文件上就可做各種操作。

document 為物件格式,裡面有許多方法及網頁元素就可讀取到。

// HTML 標籤
<h1>1234</h1>
<a class="link" href="#">連結 link</a>

先宣告 const 變數,變數名稱為 el,賦予變數 el 一個值為 “DOM 的節點”,節點要抓的網頁元素位置在 document 文件資料裡、使用 querySelector 方法來選取網頁上的元素,網頁元素為 <h1> 標籤

const el = document.querySelector('h1');   // JS 部分

程式碼拆解解釋

  • document : 在文件裡尋找
  • querySelector : 選取網頁上的元素
  • CSS 選擇器 (如 HTML 標籤、CSS 類別、id 選擇器…等) : 尋找 h1 的 HTML 標籤

至「開發人員工具」“console” 查看 <h1> 標籤 元素 (如下左圖)。

再試著使用「CSS 選擇器」來選取 <a> 標籤

const a = document.querySelector('.link');  // JS 部分

至「開發人員工具」“console” 查看 <a> 標籤 元素 (如上右圖)

以上就是透過 JavaScript 選取到網頁節點元素的操作方法。

textContent 寫入文字資料

學習對 DOM 裡的 Element 來動態修改網頁裡的 Text 文字內容。 雖然網頁寫完了,還是可以透過 JavaScript 來新增、刪除、修改網頁元素。

textContent 文字節點 : 動態更改文字內容。

// HTML 部分
<h1>1234</h1>

透過一個變數宣告起來,把變數指向到 DOM 的網頁元素位置去。直接選取變數來更改網頁文字內容、並重新賦予值。

// JavaScript 部分
const el = document.querySelector('h1'); // 此寫法較簡潔
el.textContent = "Hello World";
document.querySelector('h1').textContent = "Tom"; // 寫法冗長

前段此寫法可以使程式碼簡短,不用每次再重新寫這段程式碼document.querySelector

後段此寫法很冗長,都要重複寫document.querySelector。且此段內容會覆蓋前面的文字內容。

innerHTML 插入 HTML 標籤

innerHTML : 增加網頁節點結構 (放 HTML 標籤結構內容)。
innerHTML 特性 : 會把原本選取的「網頁節點」預設內容全部清空,再放入自己新增的內容。

字串頭尾可使用「反引號 ``」(ㄅ左邊) 或「雙引號 “ “」或「單引號 ’ ‘」包起來。

  • 字串頭尾若使用「單引號 ’ ‘」包起來,內層的 class 屬性要使用「雙引號 “ “」,否則 JavaScript 無法判斷這是屬性還是字串會跳錯。
  • 建議作法 : 字串頭尾若使用「反引號 ``」(ㄅ左邊)包起來,才不會與內層的屬性或變數有衝突。
// HTML 
<div class="main">
<p>hello!</p>
</div>

針對 <div class="main"> 來新增 <h1> 標籤

  • 選取 <div class="main"> 網頁元素,希望可以增加網頁結構,網頁結構為自己組出的字串資料。
// JavaScript
const main = document.querySelector('.main');
console.log(main); // (如下左圖) 選取到 main 的元素
main.innerHTML = `<h1 class="header"> 標題 </h1>`;
// (如下右圖) 放入字串格式資訊

innerHTML 加入變數

// HTML
<ul class="list"></ul>

字串內可以帶變數

// JavaScript
const list = document.querySelector('.list');
console.log(list); // (如下左圖) 先觀察是否有抓到 list 元素節點

確定有撈到 list 元素節點再繼續往下寫程式碼。

let link = "http://www.google.com.tw";
let linkName = "Google";
let content = `<li><a href=${link}> ${linkName} 連結 </a></li>`;

list.innerHTML = content + content;
console.log(list); // (如上右圖) 使用 innerHTML 插入 content 字串結構

textContent 與 innerHTML 運用差異

  • innerHTML : 可以產生出 Element 裡的內容 ( 如 元素、文字、屬性…等節點 )。新增 HTML 標籤的網頁結構 (重新編譯 DOM 節點)。
  • textContent : 只單純修改文字 (變成文字節點)。
// HTML
<div class="main"></div>

先抓取網頁元素節點

// JavaScript
const main = document.querySelector('.main');
console.log(main); // (如下左圖) 先觀察是否有抓到 main 元素節點

使用 innerHTML 來新增 HTML 標籤的網頁結構

main.innerHTML = `<h1> 標題 </h1>`;
console.log(main); // (如下 "右上" 圖)

使用 textContent 修改文字

main.textContent = `<h1> 標題 </h1>`;
console.log(main); // (如下 "右下" 圖)

setAttribute 增加 HTML 標籤屬性

setAttribute (“新增或修改的屬性”, “新增或修改的屬性內容”) : 設定 HTML 標籤裡的屬性,會帶兩個參數值。

// HTML
<a href="#">連結</a>

更改 <a> 連結 裡的屬性

// JavaScript
const myLink = document.querySelector('a');
console.log(myLink); // (如下左圖) 先觀察是否有抓到 myLink 元素節點

對網頁上的 <a> 連結 結構裡修改 href 屬性內容。

myLink.setAttribute("href", "http://www.yahoo.com.tw");

對網頁上的 <a> 連結 結構裡新增 class 屬性來改變顏色。

myLink.setAttribute("class", "red");

對網頁上的 <a> 連結 點滑鼠右鍵「檢查」至「開發人員工具」“Element” 裡可看到屬性內容已改變。 (如下右圖)

querySelectorAll 可重複選取多個元素

// HTML 
<body>
<a href="#">連結</a>
<a href="#">連結</a>

<script src="all.js"></script>
<style>
.red {
color: red;;
}
</style>
</body>

語法 document.querySelector(' ') 只會抓網頁第一個 DOM 元素

此時的 HTML 裡有兩個 <a> 連結,使用 document.querySelector(' ') 語法只會抓網頁第一個 DOM 元素。

// JavaScript
const myLink = document.querySelector('a');
myLink.setAttribute("href", "http://www.yahoo.com.tw");
myLink.setAttribute("class", "red");
console.log(myLink); // (如下左圖) 只有抓到 myLink 一個元素節點

語法 document.querySelectorAll(' ') 抓取全部相同名稱的 DOM 元素。回傳 “陣列”,需使用陣列方法來選取 DOM 做操作。

const myLinks = document.querySelectorAll('a');
console.log(myLinks); // (如下右圖) 回傳一個節點列表

使用 document.querySelectorAll(' ') 回傳一個節點列表。

由此得知,myLinks 是一個陣列。 (如下右圖)

選取陣列 myLinks 的第一筆網頁節點 DOM。

myLinks[0].setAttribute("href", "http://www.yahoo.com.tw");
myLinks[0].setAttribute("class", "red");

選取陣列 myLinks 的第二筆網頁節點 DOM,試著更改屬性內容。

myLinks[1].setAttribute("href", "http://www.google.com.tw");
myLinks[1].setAttribute("class", "red");

.innerHTML、.textContent、.getAttribute 取值方法

// HTML
<body>
<a href="http://www.yahoo.com.tw" class="red"><span>連結</span></a>

<script src="all.js"></script>
<style>
.red {
color: red;;
}
</style>
</body>
// JavaScript
const myLink = document.querySelector('a');
console.log(myLink); // (如下圖) 先觀察是否有抓到 myLink 元素節點

取出屬性 href 的內容

console.log(myLink.getAttribute("href")); // http://www.yahoo.com.tw
console.log(myLink.getAttribute("class")); // red

使用 innerHTML 取出 <a> 標籤 內的結構

console.log(myLink.innerHTML);// <span> 連結 </span> (把 HTML 結構撈出)

myLink.innerHTML 結果指向給變數 content

let content = myLink.innerHTML;
console.log(content); // <span> 連結 </span> (把 HTML 結構撈出)

使用 textContent 取出文字資料

console.log(myLink.textContent);   // 連結

表單元素取值方式

範例一 : input

// HTML
<input type="text" class="txt" value="你好嗎?">

利用 JavaScript 的方式來變動文字內容

// JavaScript
const txt = document.querySelector('.txt');
console.log(txt.value); // 你好嗎?

txt.value = "Hello!!"
console.log(txt.value); // Hello!!

範例二 : 「下拉式選單」

// HTML
<select class="list">
<option value="高雄市">高雄市</option>
<option value="台北市">台北市</option>
</select>

使用 list.value 把「下拉式選單」定位在 “XX市”

// JavaScript
const list = document.querySelector('.list');
console.log(list); // (如下左圖) 檢查是否有正確撈到 DOM 元素
console.log(list.value); // 高雄市

list.value = "台北市";
console.log(list.value); // 台北市 (如下右圖)

--

--