---
# System prepended metadata

title: DOM 操作

---

# DOM 操作
以下是對於DOM的基本操作
* 尋找DOM節點
    * getElementById
    * getElementsByClassName
    * querySelector
    * querySlectorAll
* 修改DOM節點內容
    * innnerHTML
    * textContent
    * addClass/removeClass
    * 修改CSS
* 新增DOM節點
    * appendChild
* appendChlid太麻煩怎麼辦？
    * cloneNode
* 刪除DOM節點
    * removeChild

# 尋找DOM節點
想要在網頁當中尋找某個元素的時候，以底下的HTML為範例介紹語法：
```xml!
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <script src="https://kit.fontawesome.com/d4981dc1b8.js" crossorigin="anonymous"></script>
    <title>Document</title>
    <style>
        .unfinish{
            display: none;
        }
    </style>
    
</head>
<body>
    <div class="main">
        <span class="name">潘潘</span>
        <span class="hello">，早安</span>
        <div class="flag unfinish">拜託你趕快做完事情去睡啦</div>
        <ul class="todo-list">
            <li class="todo-item" id="item1">
                休息
            </li>
            <li class="todo-item" id="item2">
                Java final project
            </li>
            <li class="todo-item" id="item3">
                verilog final project
            </li>
        </ul>
    </div>
</body>
</html>
```
### querySelector
使用CSS選取器選擇第一個符合條件的DOM，
```javascript
document.querySelector('CSS選取器語法');
```
### querySelectorAll
使用CSS選取器選擇所有符合條件的DOM：
```javascript
document.querySelectorAll('CSS選取器語法');
```

### getElementById
使用id選取唯一的DOM：
```javascript
document.querySelectorAll('idName');
```

### getElementsByClassName
使用Class名稱選擇所有符合條件的DOM：
```javascript
document.querySelectorAll('className');
```


範例（在範例的HTML的body標籤中，加入以下script）：
```javascript=
<script>
// querySelector: 只回傳第一個DOM
let name = document.querySelector('.name');
console.log(name);

// querySelector: 回傳一個陣列，裡面是DOM
let todo_item = document.querySelectorAll('li');
console.log(todo_item);

// getElementById: 只回傳一個DOM(唯一)
let item2 = document.getElementById('item2'); 
console.log(item2);

// querySelector: 回傳一個陣列，裡面是DOM
let todo_list = document.getElementsByClassName('todo-list');
console.log(todo_list);
</script>
```

# 修改DOM節點內容
取得了DOM之後，我們就可以對DOM的內容進行修改，以下列出一些修改DOM的方法：
### innnerHTML
取出DOM裡面的HTML：
```javascript
element.innerHTML
```

### textContent
取出DOM的文字內容：
```javascript
element.textContent
```
### classList/classList.add/classList.remove
增加/移除DOM的class：
```javascript
element.classList.add('className');
element.classList.remove('className');
```
:::info
增加/刪除class有什麼用呢？
可以透過增加/刪除class，改變一個元素的樣式！
:::

:::spoiler 範例程式碼
```xml=
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <script src="https://kit.fontawesome.com/d4981dc1b8.js" crossorigin="anonymous"></script>
    <title>Document</title>
    <style>
        .finish{
            display: none;
        }
    </style>
    
</head>
<body>
    <div class="flag">請讓我消失不見吧！</div>
    <div class="flag">讓我也消失不見吧！</div>
    <div class="flag">我也想消失在這個世界上...</div>
    <div class="flag">下輩子不要再投胎了...</div>
    <script>
        setTimeout(magic, 3000);
        function magic(){
            let flag = document.getElementsByClassName('flag');
            for(let i = 0;i < flag.length;i++){
                flag[i].classList.add('finish');
            }
        }
    </script>
</body>
    </html>
```
:::

範例（在範例的HTML的body標籤中，加入以下script）：
```javascript=
<script>
// 1.取出name這個DOM之後，想要取得裡面的姓名：
let name = document.querySelector('.name');
console.log(name.textContent);

// 2.取出todo-list這個DOM之後，想要取得裡面的HTML
let todo_list = document.getElementsByClassName('todo-list');
console.log(todo_list[0].innerHTML);

// 3.取出flag這個DOM之後，增加一個class `finish`，讓提示文字消失
let flag = document.getElementsByClassName('flag')[0];
console.log(flag);
flag.classList.add('unfinish');
</script>
```

### 修改CSS
與上面增加/刪除class的方法不同，我們可以直接對DOM的CSS進行修改，有下列兩種語法：

* `element.style = '屬性:屬性值;'`
* `element.style = '屬性1:屬性值;屬性2:屬性值;屬性3:屬性值;'`
* `element.style.CSS屬性 = 屬性值`

範例（在範例的HTML的body標籤中，加入以下script）：
```xml=
<script>
    let todo_item = document.getElementsByClassName('todo-item');
    for(let i = 0;i < todo_item.length;i++){
        todo_item[i].style.color = 'red';
    }
</script>
```

# 新增DOM節點：appendChild
一樣以上面的HTML當範例，我們要怎麼新增一個todo-list的項目呢？

在appendChild之前我們需要做幾件事情：
1. 使用`document.createElement('tagName')`來新增一個元素
2. 為這個元素裡面增加一些文字，或是CSS樣式
3. 取出新元素要增加的上一層標籤，例如`let parentElement = document.getElementById('idName')`
4. 使用`parentElement.appendChild(新元素)`

使用以下的script讓畫面上的todo-list增加一個新項目
```xml=
<script>
    let todo_item = document.getElementsByClassName('todo-list')[0];
    let li = document.createElement('li');
    li.classList.add('todo-item');
    li.id = 'item4';
    li.innerText = '窩好累';
    todo_item.appendChild(li);
</script>
```

# appendChlid太麻煩怎麼辦？
你各位呀，請看以下的todo-list(接下來的內容都是用這個範例)：

```xml=
<ul class="todo-list" style="list-style: none;">
    <li class="todo-item" id="item1">
        <span class="date">5/23</span>
        <span class="content">與教授meeting</span>
    </li>
    <li class="todo-item" id="item2">
        <span class="date">5/26</span>
        <span class="content">投工讀履歷</span>
    </li>
    <li class="todo-item" id="item3">
        <span class="date">5/30</span>
        <span class="content">準備微積分會考</span>
    </li>
</ul>

```

如果你想要用Javascript新增一個todo-item，你該怎麼做？
這邊就不考各位了，有興趣的看看底下的範例程式碼：


```javascript=
<script>
    let todo_list = document.getElementsByClassName('todo-list')[0];
    let li = document.createElement('li');
    li.classList.add('todo-item');
    li.id = 'item4';

    let date = document.createElement('span');
    date.classList.add('date');
    date.innerText = '5/32';

    let content = document.createElement('span');
    content.classList.add('content');
    content.innerText = ' 睡覺';

    li.appendChild(date);
    li.appendChild(content);
    todo_list.appendChild(li);
</script>
```

我們可以看到這個程式相當的恐怖......所以我們需要使用聰明的方法

### cloneNode
如果我們在HTML中放一個todo-item的模板(並且把它隱藏起來)，然後想要新增新的todo-item的時候就直接複製模板，並修改裡面的內容，就可以非常快速！

```javascript=
<script>
    let todo_list = document.getElementsByClassName('todo-list')[0];
    let todo_item = document.querySelector('.template .todo-item').cloneNode(deep=true);
    todo_item.id = 'item4';
    let date = todo_item.querySelector('.date');
    date.innerText = '5/32';
    let content = todo_item.querySelector('.content');
    content.innerText = '窩想睡覺';
    todo_list.appendChild(todo_item);
</script>
```

至少比剛剛少一點程式碼了吧？這樣就可以早點寫完早點睡覺了......

    



# removeChild
語法：
```javascript=
parentElement.removeChild(child);
```

remove要做的前置作業就少了很多：
1. 取出要被刪除的元素
2. 取出要被刪除的元素，它的上一層標籤，例如`let parentElement = document.getElementById('idName')`
3. 使用`parentElement.removeChild(被刪除的元素)`

```javascript=
<script>
    let todo_list = document.getElementsByClassName('todo-list')[0];
    let todo_item3 = document.getElementById('item3');
    todo_list.removeChild(todo_item3);
</script>
```
