Previous Page
cover
JavaScript
DOM
Author: Edison Chue 2021-04-13 7 mins read

JavaScript 筆記:DOM入門

JavaScript支援文件物件模型(Document Object Model,簡稱DOM),讓JavaScript控制HTML內的元素。

Window Object

window object是一個在你打開瀏覽器就會出現的物件,代表了你瀏覽器的視窗,window object作爲一個物件當然也有其方法(methods)以及屬性(properties)。

Window Object Methods常用例子:

  • alert()
  • addEventListener()
  • clearInterval()
  • prompt()
  • setInterval()

Window Object Properties常用例子:

  • Console
  • Document
  • LocalStorage
  • SessionStorage

所以什麼是Document Object Model?

Document是一個物件,爲方便理解,這邊講的Document一律爲HTML document,換句話說這個模型中所有的HTML elements都是物件,而且他們都具有屬於自己的properties及methods。

SOFTWARE-DEVELOPMENT-DOM-Tree-DOM-Hierarchy-in-HTML88.png

document.getElementById()與document.getElementsByClassName()

<!-- 先在HTML的body裏創建以下elements -->
<body>
    <h1 id="first">My First h1</h1>
    <p class="second">This is a paragraph.</p>
    <p class="second">This is another paragraph.</p>
</body>
//getElementById(), getElementByClassName()

let myH1 = document.getElementById("first");
let mypara = document.getElementsByClassName("second");

console.log(myH1);
console.log(mypara);

console會輸出下列資訊,注意document.getElementsByClassName()回傳的是類似陣列的物件,而陣列內包含所有class="second"的物件,此例由於class="second"的元素共有兩個,所以HTMLCollection物件的length會是2。

_2021-04-02_20.02.32.png

document.querySelector()與document.querySelectorAll()

querySelector()與querySelectorAll()在概念上跟getElementById()與getElementsByClassName()是很類似的,不過querySelector()與querySelectorAll()這兩個是在HTML上做查詢(query),我們在做查詢的時候總得輸入一些關鍵字,在querySelector裏,我們則以CSS Selector作爲關鍵字,來找出我們需要控制的HTML element是什麼。

<!--同樣先在HTML創建elements,這次新增class爲second的H1-->
<body>
    <h1 id="first">My First H1</h1>
    <h1 class="second">My Second H1</h1>
    <p class="second">This is a paragraph.</p>
    <p class="second">This is another paragraph.</p>
</body>
let myH1 = document.querySelector("h1.second");
console.log(myH1); // 回傳相符CSS Selector的element

myH1 = document.querySelector(".second");
console.log(myH1); // 回傳第一個滿足CSS Selector的element,在此例就是h1.second

console.log(document.querySelectorAll(".second"));
// 回傳的是一個長度爲3(.second的物件有三個)的NodeList物件

_2021-04-02_22.06.20.png

亦可透過類似Array的index操作找到.second的element:

let seconds = document.querySelectorAll(".second")
console.log(seconds[0]); // <h1 class="second">
console.log(seconds[1]); // <p class="second">
console.log(seconds[2]); // <p class="second">

console.log(seconds.length) // Output: 3

Array, HTMLCollection 與 NodeList

Array, HTMLCollection 與 NodeList 性則上很相似,一樣具有length以及indices這兩個properties,但 HTMLCollection 與 NodeList 均沒有 push()、pop() 等Array methods。而forEach Function能用在Array以及NodeList上,HTMLCollection不行。

<body>
    <h1 id="first">My First H1</h1>
    <h1 class="second">My Second H1</h1>
    <p class="second">This is a paragraph.</p>
    <p class="second">This is another paragraph.</p>
</body>
//HTMLCollection (getElementsByClassName())
let secondElement = document.getElementsByClassName("second");
secondElement.forEach((element) => {
  console.log(element); // uncaught TypeError: secondElement.forEach is not a function
});

//NodeList(querySelectorAll())
let secondQuery = document.querySelectorAll(".second");
secondQuery.forEach((element) => {
  console.log(element); // <h1 class="second">, <p class="second">, <p class="second">
});

這就是後來大部分人都用 querySelectorAll() 而不用 getElementsByClassName() 的原因。

Element.getAttribute() 方法

getAttribute() 會回傳該網頁元素(HTML)的屬性。 如果該屬性不存在,其回傳值會是null:

let div1 = document.getElementById("div1");
let align = div1.getAttribute("align");

alert(align); // shows the value of align for the element with id="div1"

Element.remove() 方法

remove() 會移除網頁中選中的HTML elements:

var myobj = document.getElementById("demo");
myobj.remove();

Element.style object

Element.style是element物件中的一個property,能夠控制 HTML element 上的CSS Styling,注意由於JacaScript裏不允許hyphen(減號 - )出現於命名上,所以所有CSS properties都被改成camelCase:

let myButton = document.querySelector("button");
myButton.style.color = "blue"; // 直接改變myButton中的文字顏色
console.log(myButton); // 回傳<button style="color: blue;">

//亦可透過addEventListener讓Event改變button的造型
myButton.addEventListener("click", (e) => {
  e.preventDefault(); // 在此例防止button送出表單重整頁面
  e.target.style = "background-color: black; color: white";
    console.log(e.target);
    // <button style="background-color: black; color: white;">
});

myButton.style = ""; // 去除所有CSS Styling

myButton.style.background-color = "somecolor"; // 會報錯
myButton.style.backgroundColor = "somecolor"; // 正確寫法

classList物件

DOM裏的每個物件上都有其classList物件,利用classList裏的 add(), remove(), toggle() 等方法可以修改element上的CSS Classes,或是以contains() 方法來判斷某個物件是浮被賦予了某個CSS Class。

.red {
  background-color: red;
}
.blue {
  color: blue;
}
.bold {
  font-weight: bolder;
}
//add() 新增CSS類
let myP = document.querySelector("p");
myP.classList.add("bold");
//爲<p>新增多個CSS類
myP.classList.add("red", "bold");

//remove() 移除CSS類
myP.classList.remove("red");
//爲 <p> 移除多個CSS類
myP.classList.remove("red", "bold");

//toggle() 有點像開關,能反轉操作增加或移除CSS類
myP.classList.toggle("blue"); // ClassList內沒有blue,增加blue
myP.classList.toggle("blue"); // ClassList內有blue,移除blue
//contains() 是否存在該類
let flag = myP.classList.contains("blue") ;
// 結果會依據ClassList內是否存在blue而回傳true或者false
console.log(flag);

ClassList亦有類似Array的length方法以及index方法,分別能回傳元素內有多少個類名,和類名在元素中的索引值(若索引值在區間範圍外則返回 null —> 代表不存在)。