DOM이란?
- HTML 문서의 계층적 구조와 정보를 표현하며, 이를 제어할 수 있는 API (프로퍼티,메소드)를 제공하는 트리자료구조이다.
- 이때 각각의 요소와 속성, 콘텐츠를 표현하는 단위를 "노드 (node)" 라고 한다.
여기서 나오는 트리자료구조에 대해 잠깐 알아보자.
Tree Data Structure?
- 트리자료구조는 노트들의 계층구조로 이뤄진다.
- 부모,자식노드로 구성되어 노드간 계층적 구조를 표현하는 비선형 자료구조이다.
- 최상위 노드는 root노드라고하고, 자식노드가 없는 노드를 leaf노드라고 한다.
노드타입?
노드타입은 총 12개지만 중요한 노트 타입 4가지를 살펴보자.
1. 문서노드
- DOM 트리의 최상위에 존재하는 루트노드 -> 노드들의 진입점역할
- document 객체를 가리킴
- 문서당 document 객체는 유일
- window.document 또는 document로 참조가능
- document ? HTML 문서 전체를 가리키는 객체
전역 객체의 window의 document 프로퍼티에 바인딩 되어있다.
2. 요소노드
- HTML을 가리키는 객체
- HTML 요소간 중첩에 의해 부자관계를 가짐
- 문서의 구조를 표현
3. 어트리뷰트 노드
- HTML요소의 어트리뷰트를 가리킴
- 어트리뷰트가 지정된 HTML 요소의 요소노드와 연결되어 있음
- 어트리뷰트 노드는 부모노드가 없으므로 요소노드의 형제노드는 아님
- 어트리뷰트 노드를 통해 참조,변경하려면 먼저 요소노드에 접근해야함.
4. 텍스트노드
- HTML요소의 텍스트를 가리킴
- 요소노드의 자식노드, 자식을 가질수없는 leaf노드
- DOM 트리의 최종단
- 텍스트노드에 접근하려면 먼저 부모노드인 요소노드에 접근해야함.
그밖에 Comment노드(주석) , DocumentType노드 (DOCTYPE) , Document Fragment노드 (복수노드 추가 및 생성) 의 12개 노트타입이 있다.
요소노드취득
HTML의 구조나 내용,스타일을 동적으로 조작하기 위해선 제일먼저 요소노드를 취득해야한다.
그 방법엔 크게 4가지가 있다.
1) ID를 통해 요소노드 취득
const element = document.getElementById('id값')
- 중복된 ID 값을 갖는 요소가 여러개 존재할 경우, 첫 번째 요소만 반환한다.
- getElementById 메서드는 언제나 단 하나의 요소노드를 반환한다.
- 만약 id 값을 가진 HTML요소가 존재하지 않으면 null을 반환한다.
2) 태그 이름을 이용한 요소노드 취득
document.getElementsByTagName('태그이름');
//만약 모든 요소 노드를 취득하려면
document.getElementsByTagName('*');
- 인수로 전달한 태그 이름을 갖는 모든 요소 노드들을 탐색하여 반환한다.
- 여러개의 요소 노드 객체를 갖는 DOM 컬렉션 객체인 HTMLCollection 객체를 반환한다.
3) class를 이용한 요소노드취득
document.getElementsByClassName('클래스 이름');
- class 어트리뷰트 값을 갖는 모든 요소 노드들을 탐색하여 반환한다.
- 여러개의 요소 노드 객체를 갖는 DOM 컬렉션 객체인 HTMLCollection 객체를 반환한다.
4) css 선택자를 이용한 요소노드 취득
document.querySelector("selector");
- 단일요소에 접근한다.
document.querySelectorAll("selector");
- 여러 요소에 접근한다.
5) 특정 요소 노드를 취득할 수 있는지 확인
const apple = document.querySelector('.apple');
apple.matches('#fruit > li.apple') //matches 메서드 사용
- Element.prototype.matches 메서드를 통해 특정 요소 노드를 취득할 수있는지 확인한다.
- 반환값은 boolean이다.
HTMLCollection & NodeList
- DOM 컬렉션 객체이다
- 유사배열 객체이며 이터러블하다.
- for ... of 문으로 순회 가능하다.
- 노드 상태변화를 실시간으로 반영하는 live 객체이다.
하지만 for문을 사용해 순회하며 className을 바꿀시 예상치 못한 결과가 나올 수 있다.
<!DOCTYPE html>
<html lang="ko">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>HTMLCollection 오류</title>
</head>
<style>
.red {
color: red;
}
.blue {
color: blue;
}
</style>
<body>
<ul class="color">
<li class="red">one</li>
<li class="red">two</li>
<li class="red">three</li>
</ul>
</body>
<script>
const color = document.getElementsByClassName("red");
for (let i = 0; i < color.length; i++) {
color[i].className = "blue";
}
console.log(color);
</script>
</html>
위의 코드로 li의 className을 blue로 바꿔본다고 하자.
for문으로 순회하며 잘 돌아가 결과는 모두 파란색으로 나올것 같지만 실제는. . .
2번째 경우 빨간색인것을 알 수 있다.
Q. 왜 이런 결과가 나올까?
A. HTMLCollection은 live 객체이기 때문에 실시간으로 li요소를 제거하며 순회를 돌다보니 오류가 발생하는 것이다.
- 이 경우 for문을 역방향 순회하거나, HTMLCollection객체에 노드 객체가 남아 있지 않을때 까지 무한방법으로 문제를 회피할 수 있지만 가장 좋은 해결책은 HTMLCollection을 사용하지 않는것이다.
- 이런 부작용을 해결하기 위해 querySelectorAll 메서드를 사용하는 방법이 있다.
querySelectorAll은 NodeList 객체를 반환하는데, 이 객체는 non-live 객체이기 때문이다.
- 하지만 childNodes 프로퍼티가 반환하는 NodeList 객체는 live 객체이므로 주의가 필요하다.
for(let i = 0; i< childNode.length ; i++){
fruit.removeChild(childNodes[i]); //live객체로 동작한다.
}
- 노드 객체의 상태변경과 상관없이 안전하게 DOM 컬렉션을 사용하려면 HTMLCollection이나 NodeList를 배열로 변환하여 사용하자!!
(예상과 다르게 동작할때도 있고, 고차함수도 사용하지 못하기 때문)
- HTMLCollection이나 NodeList는 유사배열객체이며 이터러블하기때문에 스프레드 문법이나, Array.from 메서드를 사용하여 간단히 배열로 변환할 수 있다.
* 모던 자바스크립트 DeepDive를 참고하였습니다.
https://mandelina-code.tistory.com/58
[JS] DOM (1) - DOM이란?
DOM이란? - HTML 문서의 계층적 구조와 정보를 표현하며, 이를 제어할 수 있는 API (프로퍼티,메소드)를 제공하는 트리자료구조이다. - 이때 각각의 요소와 속성, 콘텐츠를 표현하는 단위를 "노드 (nod
mandelina-code.tistory.com
https://mandelina-code.tistory.com/59
[JS] DOM (2) - 노드 탐색 , 및 Text 조작
노드탐색 - 요소노드를 얻고, DOM트리의 노드를 옮겨다니며 탐색할 경우가 있다. - 노드탐색 프로퍼티는 모두 자체적으로 값을 갖진 않고 다른 데이터 프로퍼티 값을 읽거나 저장할 때 호출되는
mandelina-code.tistory.com
https://mandelina-code.tistory.com/62
[JS] DOM (3) - DOM 조작
DOM 조작 - DOM조작이란 새로운 노드를 생성하여 DOM에 추가하거나, 기존 노드를 삭제 또는 교체하는것을 말한다. - 성능에 영향을 주므로 최적화를 위해 주의하여 다뤄야한다. innerHTML - 요소
mandelina-code.tistory.com
https://mandelina-code.tistory.com/66
DOM(4) - attribute 조작 및 style조작
Attribute? - HTML 요소의 동작을 제어하기 위한 추가적인 정보를 제공한다. - 글로벌 어트리뷰트 :id , class ,style ,title ,lang ,hidden 등 - HTML 문서가 파싱될때 , 어트리뷰트 하나당 하나의 노드가 생성..
mandelina-code.tistory.com
'FE > JavaScript' 카테고리의 다른 글
[JS] DOM (3) - DOM 조작 (0) | 2022.05.18 |
---|---|
[JS] DOM (2) - 노드 탐색 , 및 Text 조작 (0) | 2022.05.18 |
[JS] JSON (0) | 2022.05.16 |
[JS] Prototype (0) | 2022.05.16 |
[JS] DOM - Event Flow (0) | 2022.05.12 |