딥다이브 스터디 39(DOM)

김영현·2023년 12월 7일
0
post-thumbnail

DOM

Document Object Model. 문서객체모델. HTML을 브라우저가 이해할 수 있는 자료구조(트리)인 DOM으로 파싱한다.
또한 DOM API라는 기능을 브라우저가 지원하여 DOM조작을 수행할 수 있게 해줌.


출처:https://tcpschool.com/javascript/js_dom_concept


노드

HTML ElementHTML을 구성하는 개별적 요소다.

<div class="greeting">Hello</div>

HTML ElementElement Node Object로 변환됨.
또한 속성(class등)은 Attribute Node로, 텍스트 콘텐츠는 Text Node로 변환된다.

타입

  • document node : DOM트리 최상위 유일 루트노드. 다른 노드에 접근하기 위한 entry라고 보면된다.
  • element node : HTML요소를 가리키는 객체. 중첩에의해 부자관계 형성.(div>li...)
  • attribute node : HTML요소의 속성을 가리키는 객체. 요소노드와 연결되어있다. 부모 노드가 없어서 무조건 요소노드에 접근해야한다.
  • text node : HTML 요소의 텍스트를 가리킨다. 공백도 포함된다. 자식을 가질수 없는 leaf node임.

상속

DOM을 구성하는 노드객체는 브라우저가 지원하는 호스트 객체다. 하지만 자바스크립트의 객체기에 프로토타입에 의한 상속구조를 가짐.
Object => EvenetTarget => Node =>....
모든 노드객체는 위 세가지 인터페이스를 상속받음.

이렇게 프로토타입 체인이 형성되어있다.

예를들어 input태그에 이벤트타겟을 접근하는 건 EventTarget인터페이스에서 상속받은 것이고 input을 표현하는건 HTMLInputELement를 상속받은 것이다.
또한 부모노드에 접근하기위한 .parentNode등은 Node인터페이스에서 상속받은 것이다.

하지만 공통적으로 가진 기능 외에도 개별적으로 가진 기능도 있음. input에는 value가 필요하지만 div에는 필요없다.
이처럼 필요한 기능을 제공하는 인터페이스가 따로 마련되어있음(HTMLInputElement, HTMLDivElement....).

결국 DOM은 계층적 구조와 정보표현 + DOM API를 제공하여 구조, 내용, 스타일 등을 수정할 수 있게 됨


노드 취득과 탐색

노드 취득

몰랐던 요소 노드 취득방법들만 적어보겠다.

  • Element.prototype.matches(cssSelector) : 전달된 선택자를 통해 요소취득 가능한지 확인
  • HTMLCollection(getElementByClassName로 다수 노드 취득할때) 유사배열객체+이터러블. 사용할때 그냥 깊은복사 진행해서 사용하는게 맘편함.(저번에 해봐서 안다!)
  • NodeList(querySelectorAll로 다수취득): 유사배열객체+이터러블. 참조객체가 아니라서 실시간으로 노드객체 상태 변경 반영하지 않는다.하지만 childNodes가 반환하는 NodeList는 살아있는 객체니 유의...이게뭔...😲
    그냥 둘 다 배열로 바꿔서 쓰자...

노드 탐색

당연히 취득한 노드 기준으로 탐색해야할 경우가 생김. 예를들어 부모, 자식, 형제노드!
이러한 탐색 기능은 모두 접근자기에 setter로 값 할당시 무시됨.

  • 자식(childNodes, children) : childNode는 텍스트노드 포함한 NodeList, children은 요소노드만 포함한 HTMLCollection.
  • 첫번째, 마지막 자식(firstChild, firstElementChild) : firstChild는 텍스트노드포함, firstElementChild는 텍스트노드 제외. 마지막자식은 first => last로 바꾸면됨.
  • 자식 존재 체크(hasChildNodes) : 이쯤되면 알 것 같다. 텍스트 노드 포함해서 있는지 없는지 체크! 텍스트노드 제외하고 찾으려면 children.length!
  • 텍스트 노드 탐색 : 요소노드의 바로 아래 자식임. 따라서 요소노드에다가 firstChild쓰면 됨.
  • 형제 노드(nextSibling, nextElementSibling) : 역시 이것도 element안붙으면 텍스트노드 포함, 붙으면 텍스트노드 제외. 이전형제는 next => previous로 변경.

공백 텍스트 노드

개행문자, 스페이스, 탭 등 공백은 비어있는 텍스트 노드를 생성함. HTML 요소 사이 줄바꿈도 역시 비어있는 텍스트 노드 생성함.

<div></div>
<div></div>
<div></div>
<div></div>

이러면 총 3번의 공백이 생김!

노드의 정보 취득

  • nodeType : 노드 객체 종류를 취득 숫자형임. 요소노드(1), 텍스트노드 (3), 문서노드 (9)

요소노드 텍스트 조작

  • nodeValue : 텍스트 노드 자체에 접근하여 수정

DOM 조작

DOM 조작은 새로운 노드를 생성하여 DOM에 추가하거나 기존노드 삭제 또는 교체하는 행위
=> 리플로우와 리페인트 발생하니 주의해서 다루자.

  • insertADjacentHTML : 위치를 지정해 새로운 요소 삽입. 앞, 텍스트노드 앞, 텍스트노드 뒤, 뒤 4가지 위치 가능.
  • insertBefore(newNode, childNode) : 첫번째 인수로 전달받은 노드를 두번째 인수로 전달받은 노드(메서드를 호출한 자식) 앞에 생성.
  • appendChildinsertBefore메서드를 사용하여 존재하는 노드를 다시 DOM에 추가하면 위치이동됨.
  • cloneNode([deep:true, false]) : 노드 사본 생성하여 반환. 자식노드를 모두 가져올수도 있다.

Attribute

모든 어트리뷰트 노드의 참조는 유사배열객체 + 이터러블인 NamedNodeMap객체에 담겨 요소노드 attributes프로퍼티에 저장됨.
=> 요소.attributes로 접근 가능. getter만 정의되있음. 조작하려면 setAttribute메서드를 사용해야한다.

사실 요소노드 객체에는 어트리뷰트에 대응하는 DOM 프로퍼티가 존재한다. 이들은 HTML 어트리뷰트 초기값을 가지고있음.
=> DOM프로퍼티가 최신상태라면 어트리뷰트는 초기값을 그대로 유지한다.

예를들어 setAttributevalue를 변경하면 초기값 자체(HTML 어트리뷰트)가 변경됨.
하지만 요소.value = "값"은 최신상태로 변경되지만, 새로고침하면 사라진다(DOM 프로퍼티)

모든 DOM 프로퍼티가 최신상태만 관리하는건 아니다. id같은경우는 요소.id = 값변경시 어트리뷰트도 연동되어 바뀜.
이처럼 사용자가 상호작용하여 바꿀수 있는 값은 상태가 달라지고 id처럼 아닌 값은 연동된다.

참고로 어트리뷰트 값을 취득할때 DOM프로퍼티로 취득한 값의 타입과 다를 수 있으니 유의.


스타일

  • getComputedStyle : HTML요소에 적용된 모든 스타일을 가져옴.
profile
모르는 것을 모른다고 하기

0개의 댓글