39장. DOM

Happhee·2022년 1월 3일
0

JS : Depp Dive

목록 보기
28/35
post-thumbnail

Documnet Object Model인 DOM은
HTML 문서의 계층적 구조와 정보를 표현하며 이를 제어할 수 있는 API
즉, 프로퍼티메서드를 제공하는 트리 자료구조이다
DOM API를 통해 HTML의 구조나 내용 또는 스타일을 동적으로 제어

1. 노드

트리자료 구조이며 계층구조로 이루어짐
부모노드와 자식노드로 구성

노드 객체들로 구성된 트리자료 구조
Document Object Model
root node, leaf node 가 존재

DOM은 HTML문서의 계층적 구조, 정보를 표현하며, 노드 객체의 종류.
즉, 노드 종류에 따라 필요한 기능을 프로퍼티메서드 집합인 DOM API로 제공한다
DOM APIHTML문서의 구조나 내용, 스타일을 동적으로 제어 할 수 있다

📍 HTML 요소와 노드 객체

HTML 요소
HTML을 구성하는 개별적인 요소

  • 렌더링 엔진에 의해 파싱되어 DOM을 구성하는 요소 노드 객체로 변환
  • 요소의 어트리뷰트 -> 어트리뷰트 노드
  • 요소의 텍스트 콘텐츠 -> 텍스트 노드

트리자료구조
부모노드자식노드로 구성
하나의 최상위 노드에서 시작하며, 최상위 노드는 루트노드이고 자식노드가 없는노드는 리프노드

📍 노드 객체의 타입

document node
최상위에 존재하는 루트 노드로써 document 객체를 말함
요소,어트리뷰트,텍스트 노드에 접근하려면 반드시 문서노드를 거쳐야 함

element node
문서의 구조

attribute node
요소노드에만 연결되어 있으므로, 어트리뷰트에 접근하기 위해서는 먼저 요소노드에 접근해야

text node
요소노드의 자식노드

📍 노드 객체의 상속 구조

DOM을 구성하는 노드 객체는 ECMAScript사양에 정의된 표준 빌트인 객체아니라
브라우저 환경에서 추가적으로 제공하는 호스트 객체이다
하지만, 노드 객체도 자바스크립트 객체이므로 프로토타입에 의한 상속구조를 갖는다.

Object
객체

EventTarget
이벤트를 발생시키는 객체

Node
트리 자료구조의 노드 객체

Element
브라우저가 렌더링할 수 있는 웹 문서의 요소 (HTML, XML, SVG)를 표현하는 객체

HTMLElement
웹 문서의 요소 중에서 HTML 요소를 표현하는 객체


2. 노드 취득

  • getElementById
    id는 유일한 값이어야 하므로 여러 개중 첫 번째 요소노드만 반환한다
    즉, 단 하나의 요소 노드만 반환
  • getElementByTagName -> HTMLCollection 반환 (유사배열 객체 + 이터러블)
    모든 문서 요소 노드 '*'로 취득!!
    Document.prototype.getElementByTagName
  • getElementsByClassName -> HTMLCollection 반환
    getElementByTagName 메서드와 마찬가지로 HTMLCollection 객체를 반환
    Document.prototype.getElementByClassName
    class는 중복이 가능한 값
  • querySelector
  • querySelectorAll -> NodeList
//querySelectorAll은 DOM객체인 NodeList를 반환
const $elems = document.querySelectorAll('.red');

$elems.forEach(elem => elem.className = 'blue');

HTML Collection

여러개의 요소노드 객체를 갖는 DOM 컬렉션 객체
노드 객체의 상태 변화를 실시간으로 반영하는 살아있는 DOM 컬렉션 객체
for문으로 순회 가능하다

//유사배열 객체 이면서 이터러블인 HTMLCollection을 배열로 변환하여 순회
[...$elems].forEach(elem => elem.className ='blue');

NodeList

노드 객체의 상태변경을 실시간으로 반영하지 못하는 객체
childNodes 프로퍼티가반환하는 NodeList 객체는 HTMLCollection 객체와 같이 실시간 으로 상태 변경을 반영하는 live객체로 동작함을 주의!

따라서 노드 객체의 상태 변경과 상관없이 DOM컬렉션을 사용하려면 HTML Collection 이나 NodeList 객체를 배열로 변환하여 사용하는 것을 추천!

  • CSS selector
* { 전체 선택 }
p {태그가 p }
#foo { id 선택자 foo 모두 선택 }
.foo { class선택자 foo 모두 선택 }
input [type=text] { input 요소 중에 type 어트리뷰트 값이 text인 요소 모두 선택 }
div p { div요소의 후손 요소 중 p요소 모두 선택 }
div > p { div요소의 자식 요소 중 p요소 모두 선택 }
p + ul { p의 형제 요소 중에 p 바로 뒤에 위치하는 ul요소 모두 선택 }
p ~ ul { p의 형제 요소 중에 p 뒤에 위치하는 ul 요소 모두 선택 }
a : hover { hover 상태인 a 요소 모두 선택 }
p :: before { p요소 앞에 위치하는 공간을 선택 }
//class attribute값이 banana인 첫번째 요소를 탐색하여 반환
const $elem = document.querySelector('.banana');

//취득한 요소 노드의 style.color 프로퍼티 값 변경
$elem.style.color = 'red'

id 어트리뷰트가 있으면 getElementById를 사용하고,
그 외의 경우에는 querySelector, querySelectorAll 메서드를 사용하는것을 권장

  • Element.prototype.matches
    인수로 전달한 CSS 선택자를 통해 특정요소 노드를 취득할 수 있는지 확인

3. 노드 탐색

자식 노드 탐색

  • Node.prototype.childNodes
    자식 노드 모두 탐색해 NodeList에 담아 반환

  • Element.prototype.children
    자식 노드 중에서 요소노드만 모두 탐색해 HTMLCollection에 담아 반환

  • Node.prototype.firstChild
    첫번째 자식 노드 / 텍스트 요소노드

  • Node.prototype.lastChild
    마지막 자식 노드 / 텍스트 요소노드

  • Element.prototype.firstElementChild
    첫번째 자식 노드 / 요소노드

  • Element.prototype.lastElementChild
    마지막 자식 노드 / 요소노드

자식 노드 존재 확인

  • Node.prototype.hasChildNodes사용
    존재하면 true
    존재하지 않으면 false
    텍스트노드도 포함

부모 노드 탐색

  • Node.prototype.parentNode
    텍스트 노드는 DOM 트리의 리프노드이므로 부모노드가 텍스트 노드인 경우는 없다

형제 노드 탐색

  • Node.prototype.previousSibling
    부모 노드가 같은 형제 노드 중에서 자신의 이전 형제 노드 / 텍스트 요소노드

  • Node.prototype.nextSibling
    부모 노드가 같은 형제 노드 중에서 자신의 다음 형제 노드 / 텍스트 요소노드

Element.prototype.previousElementSibling
부모 노드가 같은 형제 노드 중에서 자신의 이전 형제 노드 / 요소노드

Element.prototype.nextElementSibling
부모 노드가 같은 형제 노드 중에서 자신의 다음 형제 노드 / 요소노드


4. DOM 조작

  • innerHTML

  • insertAdjacentHTML 메서드
    beforebegin afterbegin beforend afterend

  • createElement : 요소 생성 (아무런 자식 노드도 없음)

  • createTextNode(text) : 텍스트 노드 생성

  • appendChild (childNode)
    마지막 자식으로 추가

  • insertBefore (newNode, childNode)
    마지막 인자를 null 로 하면 마지막 자식노드로 추가됨

<!DOCTYPE html>
<html>
  <body>
    <ul id="fruits">
      <li>Apple</li>
      <li>Banana</li>
    </ul>
  </body>
  <script>
    const $fruits = document.getElementById('fruits');

    // 요소 노드 생성
    const $li = document.createElement('li');

    // 텍스트 노드를 $li 요소 노드의 마지막 자식 노드로 추가
    $li.appendChild(document.createTextNode('Orange'));

    // 두 번째 인수로 전달받은 노드가 null이면 $li 요소 노드를 #fruits 요소 노드의 마지막 자식 노드로 추가
    $fruits.insertBefore($li, null);
  </script>
</html>
  • cloneNdoe([deep:true | false])
  • replaceNode(newChild, oldChild)
  • removeNode (child)

5. 어트리뷰트

HTML 어트리뷰트의 역할은 HTML 요소의 초기 상태를 지정 + 변하지 않음
하지만, 요소 노드는 2개의 상태 (초기, 최신)를 가지고 있음
따라서 최신상태를 관리할 DOM 프로퍼티가 필요

  • HTML 어트리뷰트

    • getAttribute
      취득한 어트리뷰트 값은 문자열
    • setAttribute
  • DOM 프로퍼티
    문자열일 수도 아닐수도 있음

  • data 어트리뷰트 + dataset 프로퍼티
    data- 접두사 다음에 붙인 이름을 카멜케이스로 변환한 프로퍼티를 가짐

<!DOCTYPE html>
<html>
<body>
  <ul class="users">
    <li id="1" data-user-id="7621" data-role="admin">Lee</li>
    <li id="2" data-user-id="9524" data-role="subscriber">Kim</li>
  </ul>
  <script>
    const users = [...document.querySelector('.users').children];

    // user-id가 '7621'인 요소 노드를 취득한다.
    const user = users.find(user => user.dataset.userId === '7621');
    // user-id가 '7621'인 요소 노드에서 data-role의 값을 취득한다.
    console.log(user.dataset.role); // "admin"

    // user-id가 '7621'인 요소 노드의 data-role 값을 변경한다.
    user.dataset.role = 'subscriber';
    // dataset 프로퍼티는 DOMStringMap 객체를 반환한다.
    console.log(user.dataset); // DOMStringMap {userId: "7621", role: "subscriber"}
  </script>
</body>
</html>

6. 스타일

  • style : css속성 변경
    style.border, style.width
  • className(old, new)
  • classList
    • add
    • remove
    • item
    • contains
    • toggle
profile
즐기면서 정확하게 나아가는 웹프론트엔드 개발자 https://happhee-dev.tistory.com/ 로 이전하였습니다

0개의 댓글