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) ```