本文 AI 產出,尚未審核

JavaScript – DOM 與瀏覽器 API

主題:新增 / 移除元素


簡介

在前端開發中,DOM(Document Object Model) 是連結 HTML、CSS 與 JavaScript 的橋樑。透過 DOM,我們可以在執行時動態地建立、修改或刪除頁面元素,讓網站具備即時互動的能力。
無論是加入商品卡片、顯示錯誤訊息,或是依使用者操作即時移除不需要的區塊,都離不開「新增」與「移除」元素的技巧。掌握這些基本操作,不僅能提升開發效率,也能讓程式碼更具可讀性與可維護性。

本篇文章將從 概念說明實作範例常見陷阱最佳實踐 以及 實務應用 四個面向,完整講解在瀏覽器環境下如何安全、有效地新增與移除 DOM 元素。適合剛踏入前端的初學者,也能為已有基礎的開發者提供中級層次的最佳實作參考。


核心概念

1. 何謂「節點」與「元素」

在 DOM 中,節點(Node) 是所有可被操作的基本單位,包含元素節點(Element)、文字節點(Text)與註解節點(Comment)等。本文主要聚焦於 元素節點,即 HTML 標籤所代表的物件,如 <div><li><button> 等。

2. 常用的新增方法

方法 說明 典型使用情境
appendChild() 把子節點加入到父節點的最後面 動態加入列表項目
insertBefore() 把子節點插入到參考節點之前 在特定位置插入廣告
append() / prepend()(HTML5) 可同時插入文字、HTML 字串或 Node,支援多個參數 快速插入多筆內容
replaceChild() 用新節點取代舊節點 替換舊的載入動畫

Tipappend()prepend() 會自動將字串轉成 TextNode,若要插入 HTML,請使用 insertAdjacentHTML()innerHTML

3. 常用的移除方法

方法 說明 典型使用情境
removeChild() 從父節點移除指定子節點,並回傳被移除的節點 移除已完成的任務項目
element.remove()(HTML5) 直接在目標元素上呼叫,無需知道父節點 簡化程式碼的寫法
replaceWith()(HTML5) 用新節點取代當前元素,同時移除舊元素 取代舊的按鈕樣式

注意removeChild() 會拋出 NotFoundError,若要安全移除請先檢查子節點是否真的存在於父節點之中。

4. 建立新元素的步驟

  1. 建立節點document.createElement(tagName)
  2. 設定屬性與內容element.setAttribute()、element.classList、element.textContent、element.innerHTML
  3. 插入 DOM:使用上表的新增方法之一

程式碼範例

以下示範 5 個常見且實用的 新增 / 移除 範例,均附有詳細註解。

範例 1:使用 appendChild() 動態加入清單項目

// 取得 <ul id="todo-list">
const ul = document.getElementById('todo-list');

// 建立 <li> 元素
const li = document.createElement('li');
li.textContent = '購買咖啡豆';

// 加入到 <ul> 最後
ul.appendChild(li);

說明appendChild 會把新建立的 <li> 加到父節點的 最後,適合「堆疊」式的清單。


範例 2:使用 insertBefore() 在特定位置插入廣告

const container = document.querySelector('.article-content');
const ad = document.createElement('div');
ad.className = 'ad-banner';
ad.innerHTML = '<a href="https://example.com">點我看優惠</a>';

// 取得要插入前的參考節點(例如第一段落)
const referenceNode = container.querySelector('p');

// 若參考節點不存在,fallback 為末端
container.insertBefore(ad, referenceNode || null);

說明insertBefore 需要兩個參數——新節點參考節點。若參考節點為 null,等同於 appendChild


範例 3:使用 append() 同時加入多筆內容(文字 + HTML)

const msgBox = document.querySelector('#message-box');

// 同時加入文字、HTML 以及另一個 Node
msgBox.append(
  '系統訊息:',
  document.createElement('br'),          // 換行
  '<strong>已完成</strong>',           // 會自動轉為 TextNode,若想保留 HTML 用 insertAdjacentHTML
  document.createElement('hr')
);

重點append 允許傳入 任意數量 的參數,非常適合一次性寫入多筆資料。若傳入字串,會被視為 文字節點,不會被解析成 HTML。


範例 4:使用 element.remove() 移除指定卡片(HTML5)

// 假設每張卡片都有 .card class 且包含 .close 按鈕
document.addEventListener('click', function (e) {
  if (e.target.matches('.card .close')) {
    // 找到最近的 .card 父層
    const card = e.target.closest('.card');
    // 直接呼叫 remove()
    card.remove();
  }
});

說明:使用事件委派(event delegation)可以一次監聽所有 .close 按鈕,省去為每張卡片綁定個別監聽器。


範例 5:使用 replaceWith() 取代舊的載入動畫

const spinner = document.querySelector('#loading-spinner');

// 載入完成後,用內容取代 spinner
const content = document.createElement('div');
content.id = 'main-content';
content.innerHTML = '<h1>歡迎使用本網站</h1>';

spinner.replaceWith(content);

技巧replaceWith 同時完成 移除插入,讓程式碼更簡潔。


常見陷阱與最佳實踐

陷阱 可能的結果 解決方案
直接使用 innerHTML 產生大量元素 會導致 重排 (reflow)重繪 (repaint),效能下降 使用 DocumentFragment批次 append,一次寫入多筆節點
忘記移除事件監聽器 記憶體泄漏、意外觸發舊事件 removeChildelement.remove() 前,先呼叫 removeEventListener,或使用 事件委派
在迴圈中一次一次 appendChild 每次插入都會觸發 DOM 更新,效能不佳 建立 DocumentFragment,把所有子節點先加入 fragment,最後一次性插入
使用 appendChild 插入已存在於 DOM 的節點 會把節點從原位置搬移,可能造成 UI 突變 確認節點是否已在目標容器,必要時先 cloneNode(true)
null 呼叫 removeChild 產生 TypeError 先檢查 parentNode && childNode 再執行

最佳實踐

  1. 批次操作:使用 DocumentFragmentappend(...nodes) 來減少重排。
  2. 保持語意:插入元素時,選擇最符合語意的 HTML 標籤(如 <ul>/<li><section>),有助於 SEO 與可讀性。
  3. 使用 classList 管理樣式:避免直接寫入 className,以免覆蓋既有類別。
  4. 避免過度依賴 innerHTML:若僅需插入文字,使用 textContent;若需要插入大量 HTML,先建立元素再插入。
  5. 清理資源:在元素被移除前,手動解除與之相關的 計時器、WebSocket、Observer 等,確保不留下隱藏的資源。

實際應用場景

場景 需求 建議的實作方式
動態表單 使用者點擊「新增欄位」產生更多輸入框 使用 createElement('input') + appendChild(),同時為每個欄位綁定 input 事件。
無限捲動 (Infinite Scroll) 捲動到底部時自動載入新文章 依照 API 回傳的資料,用 DocumentFragment 批次建立 <article>,最後一次 appendChild(fragment)
即時聊天 收到新訊息即時顯示在聊天視窗 append() 新的訊息 <div>,並在插入後呼叫 scrollIntoView(),確保畫面自動滾動。
可關閉的通知條 點擊「X」即移除通知 透過事件委派監聽 .close,使用 element.remove() 移除整個通知容器。
圖片懶載入 (Lazy Load) 當圖片進入視窗時才載入 觀察者 (IntersectionObserver) 觸發時,用 setAttribute('src', ...),若需要替換佔位圖則使用 replaceWith()

總結

在前端開發裡,新增與移除 DOM 元素 是最常見也最基礎的操作。透過本文的概念說明、五個實作範例、常見陷阱與最佳實踐,我們可以:

  • 快速建立安全插入有效移除 任意元素;
  • 避免效能瓶頸(如重排、記憶體泄漏);
  • 在真實專案(表單、無限捲動、即時聊天等)中靈活運用。

只要遵循 語意化、批次處理、資源清理 的原則,便能寫出乾淨、可維護且效能優秀的前端程式碼。祝你在 JavaScript 的 DOM 操作之路上,玩得開心、寫得順手!