--- title: DOM 擷取網頁元素 tags: DOM, description: --- DOM(Document Object Model) === ### 為什麼JavaScript檔案要放在``<body>``的結尾 - 因為要等``HTML``渲染完成後,``JavaScript``才能對畫面去做控制。 - 若``JavaScript``先執行,但``HTML``**尚未渲染完成**,選擇器無法對DOM做控制。 ![](https://i.imgur.com/PDdlANE.png) --- <br> ### querySelector 選擇器 :::success #### ```document.querySelector('.title');``` #### ```在整個網頁.選取網頁元素的方法('css選擇器');``` ::: - **HTML** ```htmlmixed= <body> <h1 class="title">JavaScript</h1> <script src="./all.js"></script> </body> ``` - **JavaScript** - 選取```class="title"```選擇器,再賦予給變數``el`` - 變數``el``的值,```<h1 class="title">JavaScript</h1>```,也就是變數``el``取得``.title``這個HTML元素 ```javascript= const el = document.querySelector('.title'); console.log(el); ``` <br> **可以用==類似 CSS 的撰寫方式==選取** - **HTML** ```htmlembedded= <div id="targetID"> <p>我被 elementID 選取到了</p> </div> <!-- 以下是 span 被選取到 --> <div class="targetClass"> <p> <span>我被 elementClass 選取到了</span> </p> </div> ``` - **JavaScript** ```javascript= const elementID = document.querySelector("#targetID p"); const elementClass = document.querySelector(".targetClass > p > span"); ``` 或者是 - **HTML** ```htmlembedded= <div class="div"> <p class="text">abcd</p> </div> ``` - **JavaScript** ```javascript= const text = document.querySelector('.div .text'); ``` --- <br> ### 選取HTML Tag的屬性 & 值 選取`<p>`的`data-message`的值 ```htmlmixed= <p class="orderInfo-message" data-message="姓名">必填</p> ``` 在屬性及屬性值外加上`[]`。`[data-message="姓名]` ```javascript= console.log(document.querySelector('[data-message="姓名"]')); ``` --- <br> ### 更改HTML元素內容 用css選擇器取得HTML元素,就能使用其他方法來修改內容。 - **.textContent 修改文字內容** ```htmlmixed= // HTML <body> <h1 class="title">JavaScript</h1> <script src="./all.js"></script> </body> ``` 針對已經選取的``h1``,==更改==文字內容 ```el.textContent = 'J a v a S c r i p t ';``` ```javascript= // JavaScript const el = document.querySelector('.title'); el.textContent = 'J a v a S c r i p t '; ``` - **.innerHTML 插入HTML標籤** ```htmlmixed= // HTML <div class="div"> <h3>12345</h3> </div> ``` 針對已經選取的**區塊元素**``div``,==插入==HTML標籤 ``newContent.innerHTML = '<h2 class="title">54321</h2>'`` :::danger 插入HTML標籤後,原本區塊內HTML標籤會被清除取代 ::: ```javascript= // JavaScript const newContent = document.querySelector('.div'); newContent.innerHTML = `<h2 class="title">54321</h2>`; ``` - **innerHTML加入變數** 正常用``innerHTML``插入HTML標籤,會取代原有區塊的標籤。 ```htmlmixed= <ul class="list"> <li> <a href="https://www.google.com.tw">google連結</a> </li> </ul> ``` ```javascript= const el = document.querySelector('.list'); el.innerHTML = `<li><a href="https://www.yahoo.com.tw">yahoo連結</a></li>`; ``` 把JavaScript內容,用代入變數重構HTML標籤,讓innerHTML更有彈性,變化。 - 把``<a>``連結的``href``、文字內容,建立變數``href``、``linkContent``。 - 變數``htmlTag``用==樣板字面詞==引入變數使用。 - 再把變數``htmlTag``賦予到``el.innerHTML``。 - 如果有多個``htmlTag``要插入,用變數相加的方式,、賦予到``el.innerHTML``。 ```javascript= const el = document.querySelector('.list'); let href = 'https://www.yahoo.com.tw'; let linkContent = 'yahoo連結'; let htmlTag = `<li><a href="${href}">${linkContent}</a></li>` el.innerHTML = htmlTag + htmlTag; ``` --- <br> ### ``.textContent``與``.innerHTML``的差異處 - **.innerHTML**:呈現HTML標籤、DOM結構(屬性、文字) ```javascript= // HTML <div class="div"></div> // JavaScript const el = document.querySelector('.div'); el.innerHTML = `<h1>標題</h1>`; ``` ![](https://i.imgur.com/S2LFaj3.png)![](https://i.imgur.com/v1tFXNT.png) <br> - **.textContent**:只有呈現文字部分 ```javascript= // HTML <div class="div"></div> // JavaScript const el = document.querySelector('.div'); el.innerHTML = `<h1>標題</h1>`; ``` ![](https://i.imgur.com/zsdW3Xh.png) ![](https://i.imgur.com/dLQHtic.png) --- <br> ### textContent 可以跟變數混合使用 - **HTML** ```htmlembedded= <div class="targetClass"></div> ``` - **JavaScript** ```javascript= const targetClass = document.querySelector(".targetClass"); let score = 100; targetClass.textContent = `<p>小華的成績為 ${score} 分</p>`; ``` 結果: (網頁渲染出的畫面) ![](https://i.imgur.com/GH77RQV.png) (修改後的 HTML 結構) ![](https://i.imgur.com/ZrGcOr2.png) --- <br> ### setAttribute 增加 HTML 標籤屬性 ``.setAttribute('HTML屬性名稱','HTML屬性內容')`` 增加``<a>``標籤屬性``class="red"``,搭配css將文字顏色改變成**紅色** ```htmlmixed= <p>文字內容</p> <style> .red{ color: red; }; </style> ``` ```javascript= const text = document.querySelector('p'); text.setAttribute('class', 'red'); ``` --- <br> ### .querySelectorAll 可重複選取多個元素 用``.querySelectorAll``取得``document``上面==多個重複==的HTML標籤。 ```htmlmixed= <ul class="list"> <li><a href="">link1</a></li> <li><a href="">link2</a></li> </ul> ``` ```javascript= const links = document.querySelectorAll('a'); console.log(links); ``` - ``.querySelectorAll('a')``,取得``document``上面重複的``<a>``標籤,賦予給變數``links``。 - 印出變數``links``的結果,得到==陣列==形式的多個``<a>``DOM節點資料。 ![](https://i.imgur.com/2ft6RqX.png) - 因為取得的是==陣列==形式的多個``<a>``DOM節點資料,可以對不同的DOM節點資料進行修改。 ```javascript= const links = document.querySelectorAll('a'); links[0].textContent = `google連結`; links[0].setAttribute('href', 'http://www.google.com.tw'); links[1].textContent = `yahoo連結`; links[1].setAttribute('href', 'http://www.yahoo.com.tw'); ``` --- <br> ### .innerHTML、.textContent、.getAttribute取值方法 - **``.getAttribute``取得屬性** ```htmlmixed= <div class="div"> <h1 class="title">標題</h1> </div> ``` - 選擇器先選取``<h1>``標籤,賦予變數``el``。 - 再用``.getAttribute``取得``<h1>``的class屬性。 ```javascript= const el = document.querySelector('h1'); const content = el.getAttribute('class'); console.log(content); // title ``` - **``.textContent``取得文字內容** ```htmlmixed= <div class="div"> <h1 class="title">標題</h1> </div> ``` - 選擇器先選取``<h1>``標籤,賦予變數``el``。 - 再用``.textContent``取得``<h1>``的文字內容。 ```javascript= const el = document.querySelector('h1'); const content = el.textContent; console.log(content); // 標題 ``` - **``.innerHTML``取得區塊節點結構** ```htmlmixed= <div class="div"> <h1 class="title">標題</h1> </div> ``` - 選擇器先選取``class``div標籤,賦予變數``el``。 - 再用``.innerHTML``取得``<div>``內的節點結構。 ```javascript= const el = document.querySelector('.div'); const content = el.innerHTML; console.log(content); // <h1 class="title">標題</h1> ``` --- <br> ### 表單元素取值方式 - **input取值** ```htmlmixed= <input type="text" class="input" value="你好嗎"> ``` - 選擇器先選取``class``input標籤,賦予變數``el``。 - 再用```el.value```,取得input表單內容,再賦予給變數``content``。 ```javascript= const el = document.querySelector('.input'); const content = el.value; console.log(content); // 你好嗎 ``` - **select取值** ```htmlmixed= <label for="city">城市</label> <select name="city" class="cityList" id="city"> <option value="台中">台中</option> <option value="高雄">高雄</option> </select> ``` - 選擇器先選取``class``cityList標籤,賦予變數``selectOption``。 - 再用```selectOption.value```,取得select表單內容,再賦予給變數``value``。 ```javascript= const selectOption=document.querySelector('.cityList'); const value = selectOption.value; console.log(value); // 台中 ``` - **select取多個值** - 用``.querySelectorAll``取到select表單內全部的``option``,再賦予給變數``value``。 - 變數``value``的資料結構,第一層是陣列,第二層是物件。 ![](https://i.imgur.com/PrAx4HJ.png) - 第二層的物件屬性``length``,可以看見select表單內全部的``option``的資料長度。 ![](https://i.imgur.com/OofKNRS.png) - 第二層的物件屬性0是第一個option內容,用``[0]``或``['0']``取屬性內容,再進去一層用.value取select表單``option``值。 - 第二層的物件屬性1是第二個option內容,用``[1]``或``['1']``取屬性內容,再進去一層用.value取select表單``option``值。 ![](https://i.imgur.com/zX3pd6I.png) ```javascript= const selectOption = document.querySelectorAll('.cityList'); const value = selectOption; console.log(value); console.log(value[0]['0'].value); // 台中 console.log(value[0]['1'].value); // 高雄 ``` <br> --- ### `.value` 取出的值是「字串」 這邊以 input 的 value 取值為例,請觀看以下範例: HTML ```htmlembedded= <input type="text" id="targetInput"> <button type="button" id="triggerBtn">觸發按鈕</button> ``` JS ```javascript= const el = document.querySelector('#targetInput'); const triggerBtn = document.querySelector('#triggerBtn'); triggerBtn.addEventListener('click', function(e){ console.log(el.value); console.log(typeof(el.value)); }) ``` 如果在 input 輸入數字 123 以後點選「觸發按鈕」,可以在 console 中觀察到以下結果: ![](https://i.imgur.com/18bzrew.png) > `.value` 取出來的值為字串 **因此如果要對表單的「數值」進行運算,請記得要先使用 `parseInt` 做型別轉換。** 範例如下: HTML ```htmlembedded= <input type="text" id="targetInput"> <button type="button" id="triggerBtn">觸發按鈕</button> ``` JS ```javascript= const el = document.querySelector('#targetInput'); const triggerBtn = document.querySelector('#triggerBtn'); triggerBtn.addEventListener('click', function(e){ let newValue = parseInt(el.value); // 轉為 Number console.log(newValue); console.log(typeof(newValue)); }) ``` 結果: ![](https://i.imgur.com/k18ol8z.png) <br> ### `.value`, `.getAttribute('value')` 的差異 HTML ```htmlembedded= <input type="text" id="targetInput" value="123"> <button type="button" id="triggerBtn">觸發按鈕</button> ``` JS ```javascript= const el = document.querySelector('#targetInput'); const triggerBtn = document.querySelector('#triggerBtn'); console.log(`el.value: ${el.value}`); triggerBtn.addEventListener('click', function(e){ el.value = "任意填入的值"; console.log(`el.value: ${el.value}`); }) ``` console 結果: ![](https://i.imgur.com/HYHEDTk.png) 看到這邊,同學是不是認為 `<input type="text" id="targetInput" value="123">` 這行程式碼的 `value="123"` 應該已經被修改為 `value="任意填入的值"` 了? >不過,如果我們將程式碼修改如下,並一樣的點選「觸發按鈕」觀察結果: HTML ```htmlembedded= <input type="text" id="targetInput" value="123"> <button type="button" id="triggerBtn" >觸發按鈕</button> ``` JS ```javascript= const el = document.querySelector('#targetInput'); const triggerBtn = document.querySelector('#triggerBtn'); triggerBtn.addEventListener('click', function(e){ el.value = "任意填入的值"; console.log(`el.value: ${el.value}`); console.log(`el.getAttribute('value'): ${el.getAttribute('value')}`); }) ``` 可以發現網頁上 input 欄位「輸入的值」的確已經被更改為 "任意填入的值" ![](https://i.imgur.com/dI37ggU.png) 但是 `el.value` 與 `el.getAttribute('value')` 卻是不一樣的,呈現結果如下: ![](https://i.imgur.com/1RXP4aB.png) **由此可知,修改 `el.value` 不等於修改 HTML 標籤的 value 屬性值** ### 統整: * `el.value` 對應的是 input 欄位目前「輸入的值」 * `el.getAttribute('value')` 對應的是 input 標籤的「預設屬性值」 * 修改 `el.value` 並不會影響 input 標籤的 value 預設屬性,使用 `setAttribute()` 才會。 ### 補充 `e.target.value` 在[前一天](https://hackmd.io/Wl1vhP5RRR-6W-p1MnI3Mg)有提到事件監聽內函式有一個參數(這邊以 e 表示),e 是一個物件,其中有一個 target 屬性為觸發事件時的元素,此時就可以直接利用 `e.target` 搭配 `.value` 來取得該表單元素觸發事件時的值。 HTML ```htmlembedded= <select name="num" class="num"> <option value="1">1</option> <option value="2">2</option> <option value="3">3</option> </select> ``` JS ```javascript= const num = document.querySelector('.num'); num.addEventListener('change', function(e) { // 當 select 選項改變時就會觸發 // 觀察下方印出的值 console.log(e.target); console.log(e.target.value); console.log(typeof(e.target.value)); }); ```