[Note] JS: DOM & DOM manipulation


Posted by urlun0404 on 2022-10-22

摘要MDN對DOM的定義:

  1. The data representation of the objects that comprise the structure and content of a document on the web;

  2. A programming interface for web documents;

  3. The DOM represents the document as nodes and objects; that way, programming languages can interact with the page.

大意是說,DOM(Document Object Model)是瀏覽器對HTML文件(document)元素轉換成節點(node)和物件(object)的結構化表現,同時提供程式語言操作節點和物件的方法。

簡而言之就是,瀏覽器會將HTML元素和內容(包含文字與註解)轉換成程式語言可以操作的節點和物件,讓使用者可以跟HTML頁面互動。


HTMLCollection、NodeList

有些操作元素方法會將元素以 HTMLCollection 型別回傳,有些則將元素以 NodeList 型別回傳,這兩者的差異在於:

  • HTMLCollectionlife collection,如果對HTML頁面元素作任何改變,會立刻反映在回傳的元素:例如原本要選取的元素有4個,直接在developor tools inspect 刪除一個要選取的元素標籤,則選取元素的HTMLCollcetion結果會變3個;
  • 相反地, NodeList 不是life collection,若如上述刪除標籤不會讓回傳的 NodeList 元素數量有任何改變;意即,除非JavaScript檔案已經寫好要執行那些事件才會刪除元素,否則使用者"直接對頁面元素作操控"都不會影響接下來瀏覽器選取元素的結果有任何改變,仍然是4個。



DOM Manipulation

以下筆記JavaScript操作DOM的一些常用方法:

Selection

/* Selection */
// 選取整個頁面
document.documentElement

// 選取 <head> 或 <body>
document.head
document.body

// 選取元素 (return NodeList)
document.querySelector(/* CSS selector */);
docement.querySelectorAll(/* CSS selector */);

// 選取元素 (return HTMLCollection)
docement.getElementById(/* HTML id name */);
document.getElementsByClassName(/* HTML classes */);
document.getElementsByTagname(/* HTML tags */);


// 選取 children、descendents
elem.childNodes   // 可取得子、子孫、子子孫等元素
elem.children   // 只能取得子元素


// 選取 parent
elem.parentNode
elem.parentElement
elem.closest(/* CSS selector */)
elem.closest('elem')   // self-selection


// 選取 siblings
elem.previousSibling
elem.previousElementSibling
elem.nextSibling
elem.nextElementSibling
elem.parentElement.children   // DOM traversal

容易搞混的選取方法:

Creation and Insertion

/* Creation */
const elem = document.createElement(/* tag */);


/* Insertion */
elem.insertHTML = '';
elem.insertText = '';
elem.insertAdjacentHTML(position, text);   // 
elem.prepend(another);   // 插入成第一個子元素(child)
elem.append(another);   // 插入成最後一個子元素(child)

elem.append(el.cloneNode(true));   // 複製元素並插入(※若沒有複製元素,以上都是直接插入或"移動"原元素,不會讓同個元素重複出現在頁面)

elem.before(another);   // 並行插入在elem元素前(sibling)
elem.after(another);   // 並行插入在elem元素後(sibling)


Deletion

/* Deletion */
elem.remove();
elem.parentElement.removeChild(elem);


Class

/* Class */
elem.classList.add('class1', 'class2', ...);
elem.classList.remove();
elem.classList.toggle();
elem.classList.contains();


Attribute

/* Attribute */
// Built-in attributes
elem.alt
elem.className   // 選取class屬性

// Data attributes (data-subName)
// <div data-subname = "data attr">
elem.dataset.subName


// Non built-it attributes
elem.getAttribute('custom-attr');
elem.setAttribute('custom-attr', value);

imgElem.src;   // Absolute path (e.g., https:// localhost: 8080/ img1.jpg)
imgElem.getAttribute('src');   // Relative path (real attr value, e.g., /img1.jpg)

Attribute要注意的是「直接用屬性名稱」和用「getAttribute()
方法的差異,如上最後範例:

  • 直接用屬性名稱 imgElem.srcaElem.href 會拿到絕對路徑;
  • 若是用 getAttribute() 方法取得 imgElem.getAttribute('src')aElem.getAttribute('href') 會拿到真正的屬性值,如果是設定相對路徑就會拿到相對路徑。

Styles

/* Styles */
// Inline styles (if inline styles exist)
elem.style.color = '#fff';
elem.style.backgroundColor = '#37383d';


// Get current styles (include css styles in .css file)
getComputedStyle(elem).color;   // rgb(255, 255, 255)
getComputedStyle(elem).height;   // 40px


// Set styles (inlcude css styles in .css file)
elem.style.setProperty(property name, value);
    // e.g. 1, change property style document.documentElement.style.setProperty('background-color', 'yellow')
    // e.g. 2, change css variable style document.documentElement.style.setProperty('--color-primary', 'yellow')

樣式要注意以下幾點:

  • .style.xxx 是HTML的標籤元素真的有inline style才會有作用,否則回傳空字串。
  • getComputedStyle() 可以真正取得套用CSS樣式(包含用 .css 套用樣式)的元素樣式,並回傳 包含單位的CSS樣式字串
    • 可以用 Number.parseIntNumber.parseFloat 等方法取得沒有單位的number型別數值。
  • 若要改變 .css 檔案設定的屬性或CSS變數,可以用 style.setProperty() 方法。


References
The Complete JavaScript Course 2022: From Zero to Expert!
Introduction to the DOM
Document Object Model (DOM)
Element.closest()
Element.insertAdjacentHTML()
CSSStyleDeclaration.setProperty()


#frontend #javascript #vanilla javascript







Related Posts

後端好朋友 Express 基本介紹與操作

後端好朋友 Express 基本介紹與操作

利用 Stencil 建構 Web Component

利用 Stencil 建構 Web Component

Avoid blocking by navigation menu on mobile device

Avoid blocking by navigation menu on mobile device


Comments