Jeff的隨手筆記

學習當一個前端工程師

0%

『Day -16』DOM Node 的建立、刪除與修改

上一篇提到DOM 是一種樹狀結構,而樹狀結構特別擅長查找資料。

因此這篇章就是要來認識「查找 DOM 元素」的相關語法。

查找 DOM 元素有兩種途徑:

  • 直接選出一個節點 (select) - 要在樹狀結構裡查找資料,至少要先選出第一個元素
  • 從一個特定節點,查找到週邊的節點 - 選出一個元素後,就可以順著結構找出父元素、子元素 、甚至同一層的兄弟元素,這種行為稱為「遍歷 (traverse)」。 首先我們先從選出特定 DOM 節點開始:

特定 DOM 節點

這次的案例:

Imgur

querySelector & querySelectorAll

querySelector

語法:

1
document.querySelector(CSS-selector)

querySelector 用 CSS 選擇器來找元素,因此在括號裡下字串的方式,和平常寫 CSS 選擇器的邏輯是一模一樣。我們就來試試看來把

    裡的選項抓出來:

    Imgur

    但如果我今天想要抓出所有

  • 的話就不能使用這個,我們可以試一下:

    Imgur

    我們可以看到使用這個methods只會return 第一個滿足條件的element。

    因此如果我們想要抓出全部的就必須使用另外一個methods。

    querySelectorAll

    語法:

    1
    document.querySelectorAll(CSS-selector)

    Imgur

    這樣所有滿足條件的都會 return 。

    另外我們注意看一下,return 回來的是一個NodeList,什麼是NodeList啊?

    NodeList

    NodeList 是一個 JavaScript Object,它表示了一個節點(Node)的集合。

    NodeList 很類似於Array ,但它並不是真正的 Array。

    它不能新增刪除元素,只有幾個簡單的唯讀操作:

    • 查看長度 length
    • 遍歷內容 forEach
    • 使用 index 來存取特定項目

    Imgur

    getElementBy家族

    這個系列的語法是用字串來搜尋,不是 CSS 選擇器

    我們在昨天有提到『大多數人使用 querySelector 系列而不使用 get 系列』,但有一個語法是例外,那就是getElementById

    至於原因我詢問了chat GPT,我是覺得蠻合理的啦,大家也可以看一下:

    1. 簡單易用: getElementById 是一個簡單的方法,適合於簡單的頁面操作。只需要提供元素的 ID,就可以快速地獲取該元素,不需要特別的選擇器語法。
    2. 效能: getElementById 是一個非常快速的方法,因為它在 DOM 中直接使用元素的 ID 進行查找,而不需要額外的選擇器解析和比對。
    3. 元素唯一性: 每個網頁中的元素 ID 應該是唯一的。這使得使用 getElementById 取得的元素確實是唯一的,不會有多個元素匹配。

    然而,也有一些限制和考慮因素:

    1. 僅限於 ID: getElementById 只能使用元素的 ID 進行選取。如果您想使用其他屬性或複雜的選擇器來選取元素,則需要使用其他 DOM 選取方法,如 querySelector 或 **querySelectorAll**。
    2. 不支援動態內容: 如果您的網頁內容是動態生成的,並且元素的 ID 是在後續添加的,則 getElementById 可能無法正確地找到這些動態添加的元素。

    修改DOM節點

    現在我們先來學習如何新增element,並呈現在畫面上。

    我們會利用到3個語法:

    • document.createElement 新增一個元素
    • NODE.innerHTML 修改元素的文字
    • NODE.appendChild 將元素插入現有 DOM 結構中:

    Imgur

    我們可以看到上面這個圖片,html的body裡面,只有一個

    的標籤但是,因為我們在JavaScript上打上了3段code,就讓我們的畫面多出了一段文字。這就是最基本的DOM的語法。

    innerText 與 textContent

    innerText 和 textContent 通常都被使用於「取得元素內的文字」,但兩者之間有什麼差別?

    在MDN上是這麼說的:

    Node.innerText 是一個代表節點及其後代之「已渲染」(rendered)文字內容的屬性。

    **Node.textContent** 屬性表示了節點或其後代的文字內容。

    總結來說,如果您需要操作元素的 HTML 內容,可以使用 **innerHTML**。如果您只需要處理元素的純文本內容,則應使用 **innerText**。

    節點插入 DOM Tree

    我們在剛剛的案例有一個語法NODE.appendChild 將元素插入現有 DOM 結構中,除了這個以外我們還有其他兩個方法:

    • NODE.insertBefore
    • NODE.replaceChild

    我們來認識一下這三個方法的不同吧

    NODE.appendChild

    將一個節點附加到另一個節點的子節點列表的末尾。

    Imgur

    圖片來源:AC教案

    NODE.insertBefore

    在指定節點之前插入新的節點。

    Imgur

    圖片來源:AC教案

    NODE.replaceChild

    替換一個子節點為另一個節點。

    Imgur

    圖片來源:AC教案

    在了解後,我們來用這3個方法把剛剛案例完成吧。

    Imgur

    感覺有點冗長,但主要是為了復原原本的例子,早知道原本範例打少一點XDD

    補充:

    這是一個IE不支援的語法,但….IE已經不在了~~~所以全部的瀏覽器都可以用XDD

    Imgur

    圖片來源:AC教案

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    const container = document.querySelector(".card-body");
    const h1 = document.createElement("h1");
    h1.innerHTML = "Professional Sports";
    const ul = document.createElement("ul");
    container.appendChild(h1);
    container.appendChild(ul);
    const li_1 = document.createElement("li");
    const li_2 = document.createElement("li");
    li_1.innerHTML = "NFL";
    li_2.innerHTML = "MLB";
    ul.prepend(li_1);
    ul.append(li_2);
    ul.prepend("NBA");

    我們會看到:

    Imgur

    這套語法的撰寫風格比較簡潔,而且同時可以插入節點或文字。提供給大家參考。

    刪除節點

    parentElement.removeChild(NODE)

    這個方法是用來從指定的父節點中移除子節點 **NODE**。例如:

    1
    2
    3
    const parent = document.querySelector(".parent");
    const child = document.querySelector(".child");
    parent.removeChild(child);

    NODE.remove()

    這個方法可以直接從 DOM 中移除特定的節點 **NODE**。例如:

    1
    2
    const element = document.querySelector(".element");
    element.remove();

    操作 CSS

    NODE.classList

    這是一個用來操作節點的 class 名稱的屬性。它會回傳一個類似陣列的物件,可以用來新增、刪除、查看 class 名稱。

    1
    2
    3
    4
    const element = document.querySelector(".element");

    element.classList.add("new-class");//增加
    element.classList.remove("old-class");//刪除

    NODE.className = className

    這個屬性直接設定節點的 class 名稱,但注意這會將目前節點的所有 class 都替換掉。

    1
    2
    const element = document.querySelector(".element");
    element.className = "new-class";

    DOM 也有提供 style 屬性,例如:NODE.style.backgroundColor ,但為了讓程式碼一目瞭然地被歸類在它們應該在的位置,建議還是先寫好 CSS 文件,再透過 classList 等方法去修改樣式。


    DOM真的是我目前為止打最久的一個主題吧(未來的原型可能會超過),主要原因有兩個:1.真的很久沒有用這些語法了都忘了差不多了。2.就是我之前的筆記看不懂…導致我再回去把課程重上。

    這次的教訓就是,筆記要認真做而且三不五時要回去更新,之前做筆記還會分發芽期、培育期、長青期,目的就是要讓自己回去檢視過去是否有理解錯誤的地方,結果這次在整理筆記發先我所有的筆記都是發芽期,培育期少之又少,長青期更是完全沒有。

    明天就是遍歷(traverse)了,終於要結束這個主題了~