---
# System prepended metadata

title: 第 24 節： Introducing The World Of The DOM
tags: [The Web Developer Bootcamp 2021, JavaScript, Udemy]

---

Udemy課程：[The Web Developer Bootcamp 2021（Colt Steele）](https://www.udemy.com/course/the-web-developer-bootcamp/)
# 第 24 節： Introducing The World Of The DOM
###### tags: `JavaScript` `Udemy` `The Web Developer Bootcamp 2021`
2021.03.17（Wed.）～04.08（Thu.）
## ● 上課筆記
## DOM
> D：DOCUMENT 文件
> O：OBJECT   物件
> M：MODEL    模型

先看看MDN是如何解釋DOM的：

**文件物件模型（Document Object Model, DOM）** 是 HTML、XML 和 SVG 文件的程式介面。它提供了一個文件（樹）的結構化表示法，並定義讓程式可以存取並改變文件架構、風格和內容的方法。DOM 提供了文件以擁有屬性與函式的節點與物件組成的結構化表示。節點也可以附加事件處理程序，一旦觸發事件就會執行處理程序。 本質上，它將網頁與腳本或程式語言連結在一起。

雖然常常使用 JavaScript 來存取 DOM，但它本身並不是 JavaScript 語言的一部分，而且它也可以被其他語言存取（雖然不太常見就是了）。

其他詳細內容可參考：[深入理解網頁架構：DOM](https://ithelp.ithome.com.tw/articles/10202689)

****
## DOM操作語法
> 參考資料：[DOM概念](https://ithelp.ithome.com.tw/articles/10094965)
> 覺得這邊有個要注意的點，就是element後面要不要加s（是單數還是複數）
****
## 1. getElementById()
Document的方法 getElementById()返回一個匹配特定 ID的元素. 由於元素的 ID 在大部分情況下要求是獨一無二的，這個方法自然而然地成為了一個高效查找特定元素的方法。

* 範例：
```javascript=
var choose = document.getElementById("choose")
//可以取出 HTML 內容當中 <div id=”choose”> test </div> 當中的 test 字串
```

## 2. getElementsByTagName()
返回的 HTML集合是動態的, 意味著它可以自動更新自己來保持和 DOM 樹的同步而不用再次調用 document.getElementsByTagName() 。

* 用法：
```javascript=
document.getElementsByTagName("標籤名稱")
```

* 範例：
```javascript=
document.getElementsByTagName("p")
//會回傳文件當中的所有 <p> 元素內之內容
```

## 3. getElementsByClassName()
當呼叫 document 物件時，它會搜尋整個文件，包括根節點在內。你也可以在所有元素呼叫 getElementsByClassName()，那它就只會回傳含有給定 class 的特定根元素的後代元素。

## 4. querySelector / querySelectorAll

**querySelector**
回傳 document 第一個符合特定選擇器群組的元素（採用深度優先，前序追蹤 document 節點）。
* 範例：
```javascript=
document.querySelector("p")
//會回傳文件當中的所有 <p> 元素內之內容
```
可參考網址：[JavaScript 基礎知識-querySelector](https://ithelp.ithome.com.tw/articles/10211605)

**querySelectorAll**
至於querySelectedAll的話，差別就在於querySelector他採用深度優先，前序追蹤 document 節點，所以假如我抓"p"的話，只會抓到最前面的第一個p，因此querySelectedAll顧名思義就是我抓"p"，所有的p都會被我抓出來。

另外querySelectorAll抓到全部後，會存成一個陣列，所以想要利用他時，要用陣列的方式取得。
* 範例：

html的部分：
```htmlmixed=
<h2 class="title">1</h2>
<h2 class="title">2</h2>
<h2 class="title">3</h2>
<h2 class="title">4</h2>
```
JavaScript的部分：
```javascript=
var allTitle = document.querySelectorAll("title")

console.log(allTitle[0]) //1
console.log(allTitle[1]) //2
console.log(allTitle[2]) //3
console.log(allTitle[3]) //4

//要全部都取得，就要用陣列的方法：for迴圈
for(var i = 0; i < allTitle.length; i++){
    console.log(allTitle[i])
}
//1,2,3,4
```
****
```
元素類型：
1. 標籤元素
2. class元素
3. id元素
```
**當選取class元素 -> 用點點（.）**
```javascript=
document.querySelector(".title")
```
**當選取id元素 -> 用井字號（#）**
```javascript=
document.querySelector("#title")
```

## 5. innerHTML / textContent / innerText
**innerHTML**
innerHTML設定或獲取標籤所包含的HTML 文字資訊(從標籤起始位置到終止位置全部內容，包括HTML標籤，但不包括自身)
1. 他會顯示所有標籤

**textContent**
textContent屬性表示了節點或其後代的文字內容。
1. 假設在css設定display:none，用textContent仍看得到

**innerText**
innerText設定或獲取標籤所包含的文字資訊（從標籤起始位置到終止位置的內容，去除HTML標籤，但不包括自身）
1. 假設在css設定display:none，用innerText會看不到
2. 只能單純改文字，如果想新增或更改新標籤，就要用innerHTML

## 6. classList
可參考網址：[JS基礎篇–HTML DOM classList 屬性](https://codertw.com/%E5%89%8D%E7%AB%AF%E9%96%8B%E7%99%BC/27430/)

頁面DOM裡的每個節點上都有一個classList物件，程式設計師可以使用裡面的方法新增、刪除、修改節點上的CSS類。

**add**
新增class = "purple"（css中已經有設置名為purple的class）到h2上面
之後再新增class = "border"（css中已經有設置名為border的class）
```javascript=
h2.classList.add("purple")
h2.classList.add("border")
```

另一種方法：
```javascript=
h2.addClass("purple")
h2.addClass("border")
```

**remove**
有新增的功能，相對地一定有移除功能！
```javascript=
h2.classList.remove("border")
```

另一種方法：
```javascript=
h2.removeClass("border")
```

**contains**
contains這個用在你想確定那個class是否有存在？
例如說，我上面remove掉border這個class了，並且沒有其他border存在h2裡面，但我還是想做確認（可能class太多沒辦法馬上看出來之類的），就可以用contains。
```javascript=
h2.classList.contains("border")
//若回傳False則表示不存在
//若回傳True則表示還存在著
```

**toggle**
這個用處就是狀態交換，例如原本存在，用了toggle之後就會不存在；相反地原本若不存在，利用了toggle就會變成存在的。
（用在ckeck list、todo list、狀態來回變換的東西上很好用）
```javascript=
//假如purple這個class原本存在
h2.classList.toggle("purple") //false
//purple不存在了

h2.classList.toggle("purple") //true
//purple又存在了
```
****

classList這裡抓元素時前面不需要點點（.）的原因，放上之前在Hahow提問過，得到的回答：
![](https://i.imgur.com/qz9bjJS.jpg)

## 7. Traversing Parent / Child / Sibling
**parentElement**
當前節點的父元素，此處b的父元素就是p
```htmlmixed=
<p>
    <b>Silkie</b>
</p>
```
```javascript=
const firstBold = document.querySector("b")
console.log(firstBold) //<b>Silkie</b>
console.log(firstBold.parentElement) //<p>...</p>
```

**children**
當前節點的子元素，可能會有多個，此處p的children就有b,b,a,a
```htmlmixed=
<p>
    <b>Silkie1</b>
    <b>Silkie2</b>
    <a>link1</a>
    <a>link2</a>
</p>
```
```javascript=
var paragraph = firstBold.parentElement
paragraph.children //[b,b,a,a]

paragraph.children[0] //<b>Silkie1</b>
paragraph.children[1] //<b>Silkie2</b>
paragraph.children[2] //<a>link1</a>
paragraph.children[3] //<a>link2</a>
```

****
先來個html的部分：
```htmlmixed=
<p>
    <b id="b1">Silkie1</b>
    <b id="b2">Silkie2</b>
    <a id="a1">link1</a>
    <a id="a2">link2</a>
</p>
```
**previousSibling**
可以得到當前節點的前一個兄弟節點，如果沒有則回傳null
```javascript=
const b1 = document.getElementById("b1")
const a2 = document.getElemnetById("a2")
b1.previousSibling //null
a2.previousSibling //<a id="a1">link1</a>
```

**nextSibling**
可以得到當前節點緊跟在後的兄弟節點，如果沒有則回傳null
```javascript=
const b1 = document.getElementById("b1")
const a2 = document.getElemnetById("a2")
b1.nextSibling //<b id="b2">Silkie2</b>
a2.nextSibling //null
```

## 8. Append / AppendChild

```javascript=
const parent = document.createElement("div")
const child = document.createElement("p")
const child2 = document.createElement("p")

//插入節點Node物件
parent.append(child) //<div><p></p></div>
parent.appendChild(child) //<div><p></p></div>

//插入DOMString
parent.append("文字") //<div>文字</div>
parent.appendChild("文字") //會出現錯誤

//返回值
var appendValue = parent.append(child)
var appendChildValue = parent.appendChild(child)
console.log(appendValue) //undefined
console.log(appendChildValue) //<p></p>

//新增專案數量
parent.append(child, child2, "Hello World") //正常
parent.appendChild(child, child2, "Hello World") //也正常，但只新增第一個元素，而忽略其他元素
```

* 總整理：


|      | append() | appendChild() |
| ---- | -------- | ------------- |
|插入節點Node物件|接受|接受|
|插入DOMString|接受|不接受|
|返回值|沒有返回值|返回附加的Node物件|
|新增專案數量|允許新增多個|允許新增單個|

## 9. removeChild / remove
```javascript=
const img = document.querySelector("img")
//以下兩種寫法結果是一樣的，都可以把這張img給移除掉
img.remove()
img.parentElement.removeChild(img)
```